{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "256e246f-d908-4b29-b8f9-adaab145ee56",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Looking in indexes: https://repo.huaweicloud.com/repository/pypi/simple/\n",
      "Requirement already satisfied: download in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (0.3.5)\n",
      "Requirement already satisfied: tqdm in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from download) (4.67.1)\n",
      "Requirement already satisfied: six in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from download) (1.16.0)\n",
      "Requirement already satisfied: requests in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from download) (2.32.3)\n",
      "Requirement already satisfied: charset-normalizer<4,>=2 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from requests->download) (3.4.1)\n",
      "Requirement already satisfied: idna<4,>=2.5 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from requests->download) (3.10)\n",
      "Requirement already satisfied: urllib3<3,>=1.21.1 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from requests->download) (2.3.0)\n",
      "Requirement already satisfied: certifi>=2017.4.17 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from requests->download) (2025.1.31)\n",
      "\n",
      "\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m A new release of pip is available: \u001b[0m\u001b[31;49m25.0.1\u001b[0m\u001b[39;49m -> \u001b[0m\u001b[32;49m25.2\u001b[0m\n",
      "\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m To update, run: \u001b[0m\u001b[32;49mpython -m pip install --upgrade pip\u001b[0m\n"
     ]
    }
   ],
   "source": [
    "!pip install download"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "10f8e074-f48d-4806-a618-4c4ddbad060b",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Creating data folder...\n",
      "Downloading data from https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/notebook/datasets/cifar-10-binary.tar.gz (162.2 MB)\n",
      "\n",
      "file_sizes: 100%|█████████████████████████████| 170M/170M [00:00<00:00, 181MB/s]\n",
      "Extracting tar.gz file...\n",
      "Successfully downloaded / unzipped to ./datasets-cifar10-bin\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "'./datasets-cifar10-bin'"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from download import download\n",
    "\n",
    "url = \"https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/notebook/datasets/cifar-10-binary.tar.gz\"\n",
    "\n",
    "download(url, \"./datasets-cifar10-bin\", kind=\"tar.gz\", replace=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "ace29469-1239-4be4-b88b-8197bdfd8cec",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "import mindspore as ms\n",
    "import mindspore.dataset as ds\n",
    "import mindspore.dataset.vision as vision # 图像预处理工具\n",
    "import mindspore.dataset.transforms as transforms  # 数据转换工具\n",
    "from mindspore import dtype as mstype\n",
    "\n",
    "data_dir = \"./datasets-cifar10-bin/cifar-10-batches-bin\"  # 数据集根目录\n",
    "batch_size = 256  # 批量大小\n",
    "image_size = 32  # 训练图像空间大小\n",
    "workers = 4  # 并行线程个数\n",
    "num_classes = 10  # 分类数量\n",
    "\n",
    "\n",
    "def create_dataset_cifar10(dataset_dir, usage, resize, batch_size, workers):\n",
    "\n",
    "    data_set = ds.Cifar10Dataset(dataset_dir=dataset_dir, # 数据集路径\n",
    "                                 usage=usage, # 用途：\"train\"（训练集）或 \"test\"（测试集）\n",
    "                                 num_parallel_workers=workers,  # 并行加载线程数\n",
    "                                 shuffle=True) # 加载时是否打乱数据（训练集通常需要打乱）\n",
    "\n",
    "    trans = [] # 存储图像变换操作的列表\n",
    "    if usage == \"train\":\n",
    "        trans += [\n",
    "            vision.RandomCrop((32, 32), (4, 4, 4, 4)),  # 随机裁剪：先将图像填充4像素，再随机裁剪为32x32\n",
    "            vision.RandomHorizontalFlip(prob=0.5) # 随机水平翻转（50%概率）\n",
    "        ]\n",
    "# 训练集和测试集共有的基础预处理\n",
    "    trans += [\n",
    "        vision.Resize(resize), # 将图像大小调整为指定尺寸（这里是32x32）\n",
    "        vision.Rescale(1.0 / 255.0, 0.0),  # 像素值归一化：将 [0,255] 映射到 [0,1]\n",
    "        vision.Normalize([0.4914, 0.4822, 0.4465], [0.2023, 0.1994, 0.2010]),  # 标准化：按通道减去均值、除以标准差\n",
    "        vision.HWC2CHW()\n",
    "        # 通道顺序转换：从 (高度, 宽度, 通道) 转为 (通道, 高度, 宽度)（适配深度学习框架习惯）\n",
    "] \n",
    "   \n",
    "\n",
    "    target_trans = transforms.TypeCast(mstype.int32)  # 将标签转换为 int32 类型\n",
    "\n",
    "    # 数据映射操作\n",
    "    data_set = data_set.map(operations=trans,\n",
    "                            input_columns='image', # 针对数据集中的 \"image\" 列进行处理\n",
    "                            num_parallel_workers=workers)\n",
    "\n",
    "    data_set = data_set.map(operations=target_trans,\n",
    "                            input_columns='label', # 针对数据集中的 \"label\" 列进行处理\n",
    "                            num_parallel_workers=workers)\n",
    "\n",
    "    # 批量操作\n",
    "    data_set = data_set.batch(batch_size)\n",
    "\n",
    "    return data_set\n",
    "\n",
    "\n",
    "# 获取处理后的训练与测试数据集\n",
    "\n",
    "dataset_train = create_dataset_cifar10(dataset_dir=data_dir,\n",
    "                                       usage=\"train\",\n",
    "                                       resize=image_size,\n",
    "                                       batch_size=batch_size,\n",
    "                                       workers=workers)\n",
    "step_size_train = dataset_train.get_dataset_size()\n",
    "\n",
    "dataset_val = create_dataset_cifar10(dataset_dir=data_dir,\n",
    "                                     usage=\"test\",\n",
    "                                     resize=image_size,\n",
    "                                     batch_size=batch_size,\n",
    "                                     workers=workers)import mindspore as ms\n",
    "import mindspore.dataset as ds\n",
    "import mindspore.dataset.vision as vision # 图像预处理工具\n",
    "import mindspore.dataset.transforms as transforms  # 数据转换工具\n",
    "from mindspore import dtype as mstype\n",
    "\n",
    "data_dir = \"./datasets-cifar10-bin/cifar-10-batches-bin\"  # 数据集根目录\n",
    "batch_size = 256  # 批量大小\n",
    "image_size = 32  # 训练图像空间大小\n",
    "workers = 4  # 并行线程个数\n",
    "num_classes = 10  # 分类数量\n",
    "\n",
    "\n",
    "def create_dataset_cifar10(dataset_dir, usage, resize, batch_size, workers):\n",
    "\n",
    "    data_set = ds.Cifar10Dataset(dataset_dir=dataset_dir, # 数据集路径\n",
    "                                 usage=usage, # 用途：\"train\"（训练集）或 \"test\"（测试集）\n",
    "                                 num_parallel_workers=workers,  # 并行加载线程数\n",
    "                                 shuffle=True) # 加载时是否打乱数据（训练集通常需要打乱）\n",
    "\n",
    "    trans = [] # 存储图像变换操作的列表\n",
    "    if usage == \"train\":\n",
    "        trans += [\n",
    "            vision.RandomCrop((32, 32), (4, 4, 4, 4)),  # 随机裁剪：先将图像填充4像素，再随机裁剪为32x32\n",
    "            vision.RandomHorizontalFlip(prob=0.5) # 随机水平翻转（50%概率）\n",
    "        ]\n",
    "# 训练集和测试集共有的基础预处理\n",
    "    trans += [\n",
    "        vision.Resize(resize), # 将图像大小调整为指定尺寸（这里是32x32）\n",
    "        vision.Rescale(1.0 / 255.0, 0.0),  # 像素值归一化：将 [0,255] 映射到 [0,1]\n",
    "        vision.Normalize([0.4914, 0.4822, 0.4465], [0.2023, 0.1994, 0.2010]),  # 标准化：按通道减去均值、除以标准差\n",
    "        vision.HWC2CHW()\n",
    "        # 通道顺序转换：从 (高度, 宽度, 通道) 转为 (通道, 高度, 宽度)（适配深度学习框架习惯）\n",
    "] \n",
    "   \n",
    "\n",
    "    target_trans = transforms.TypeCast(mstype.int32)  # 将标签转换为 int32 类型\n",
    "\n",
    "    # 数据映射操作\n",
    "    data_set = data_set.map(operations=trans,\n",
    "                            input_columns='image', # 针对数据集中的 \"image\" 列进行处理\n",
    "                            num_parallel_workers=workers)\n",
    "\n",
    "    data_set = data_set.map(operations=target_trans,\n",
    "                            input_columns='label', # 针对数据集中的 \"label\" 列进行处理\n",
    "                            num_parallel_workers=workers)\n",
    "\n",
    "    # 批量操作\n",
    "    data_set = data_set.batch(batch_size)\n",
    "\n",
    "    return data_set\n",
    "\n",
    "\n",
    "# 获取处理后的训练与测试数据集\n",
    "\n",
    "dataset_train = create_dataset_cifar10(dataset_dir=data_dir,\n",
    "                                       usage=\"train\",\n",
    "                                       resize=image_size,\n",
    "                                       batch_size=batch_size,\n",
    "                                       workers=workers)\n",
    "step_size_train = dataset_train.get_dataset_size()\n",
    "step_size_val = dataset_val.get_dataset_size()import mindspore as ms\n",
    "import mindspore.dataset as ds\n",
    "import mindspore.dataset.vision as vision # 图像预处理工具\n",
    "import mindspore.dataset.transforms as transforms  # 数据转换工具\n",
    "from mindspore import dtype as mstype\n",
    "\n",
    "data_dir = \"./datasets-cifar10-bin/cifar-10-batches-bin\"  # 数据集根目录\n",
    "batch_size = 256  # 批量大小\n",
    "image_size = 32  # 训练图像空间大小\n",
    "workers = 4  # 并行线程个数\n",
    "num_classes = 10  # 分类数量\n",
    "\n",
    "\n",
    "def create_dataset_cifar10(dataset_dir, usage, resize, batch_size, workers):\n",
    "\n",
    "    data_set = ds.Cifar10Dataset(dataset_dir=dataset_dir, # 数据集路径\n",
    "                                 usage=usage, # 用途：\"train\"（训练集）或 \"test\"（测试集）\n",
    "                                 num_parallel_workers=workers,  # 并行加载线程数\n",
    "                                 shuffle=True) # 加载时是否打乱数据（训练集通常需要打乱）\n",
    "\n",
    "    trans = [] # 存储图像变换操作的列表\n",
    "    if usage == \"train\":\n",
    "        trans += [\n",
    "            vision.RandomCrop((32, 32), (4, 4, 4, 4)),  # 随机裁剪：先将图像填充4像素，再随机裁剪为32x32\n",
    "            vision.RandomHorizontalFlip(prob=0.5) # 随机水平翻转（50%概率）\n",
    "        ]\n",
    "# 训练集和测试集共有的基础预处理\n",
    "    trans += [\n",
    "        vision.Resize(resize), # 将图像大小调整为指定尺寸（这里是32x32）\n",
    "        vision.Rescale(1.0 / 255.0, 0.0),  # 像素值归一化：将 [0,255] 映射到 [0,1]\n",
    "        vision.Normalize([0.4914, 0.4822, 0.4465], [0.2023, 0.1994, 0.2010]),  # 标准化：按通道减去均值、除以标准差\n",
    "        vision.HWC2CHW()\n",
    "        # 通道顺序转换：从 (高度, 宽度, 通道) 转为 (通道, 高度, 宽度)（适配深度学习框架习惯）\n",
    "] \n",
    "   \n",
    "\n",
    "    target_trans = transforms.TypeCast(mstype.int32)  # 将标签转换为 int32 类型\n",
    "\n",
    "    # 数据映射操作\n",
    "    data_set = data_set.map(operations=trans,\n",
    "                            input_columns='image', # 针对数据集中的 \"image\" 列进行处理\n",
    "                            num_parallel_workers=workers)\n",
    "\n",
    "    data_set = data_set.map(operations=target_trans,\n",
    "                            input_columns='label', # 针对数据集中的 \"label\" 列进行处理\n",
    "                            num_parallel_workers=workers)\n",
    "\n",
    "    # 批量操作\n",
    "    data_set = data_set.batch(batch_size)\n",
    "\n",
    "    return data_set\n",
    "\n",
    "\n",
    "# 获取处理后的训练与测试数据集\n",
    "\n",
    "dataset_train = create_dataset_cifar10(dataset_dir=data_dir,\n",
    "                                       usage=\"train\",\n",
    "                                       resize=image_size,\n",
    "                                       batch_size=batch_size,\n",
    "                                       workers=workers)\n",
    "step_size_train = dataset_train.get_dataset_size()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "2848e2a8-2427-4551-83ba-0f713dca4020",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Image shape: (256, 3, 32, 32), Label shape: (256,)\n",
      "Labels: [8 0 8 4 6 0]\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAgMAAAGFCAYAAABg2vAPAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuNCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8ekN5oAAAACXBIWXMAAA9hAAAPYQGoP6dpAABpT0lEQVR4nO29eZRmVXnv/5xz3nmoemuurp7nhmZoaEVl6AYVG9QYUEFiDMM1CYPDwhW83pgbIRpDrsISgj813qyQmPC7v1wEolGZWkERENqmWxq6aXoeqru65vGdzzm/Pwy1fPZ3Y1fapqqb8/2s5ZK9+3nPuM9+93ueb30fJwzDUAghhBASWdyZPgBCCCGEzCxcDBBCCCERh4sBQgghJOJwMUAIIYREHC4GCCGEkIjDxQAhhBAScbgYIIQQQiIOFwOEEEJIxOFigBBCCIk4XAz8F7nwwgvltNNOO2rc3r17xXEc+ad/+qc3/qBIJHjyySfFcRx58sknT4rtEnK84Lz7xsPFACGEEBJxYjN9AG9W5s+fL6VSSeLx+EwfCnmTsGbNGimVSpJIJGb6UAg5IeG8e+zwzcAbhOM4kkqlxPO8mT4U8ibBdV1JpVLiur/9sS0Wi9N0RIScWHDePXa4GDAYGxuTm2++WRYsWCDJZFLa29vl4osvlhdeeEHFbd26VS666CLJZDIye/Zs+cpXvqL+3Za7uvbaayWXy8nu3btl3bp1ks1mpaurS774xS8Ki0dGl3379slNN90ky5cvl3Q6LS0tLXLFFVfI3r17VZwtt/9aLnXjxo2yZs0ayWQy8vnPf15ERBYsWCDvf//75bHHHpNVq1ZJKpWSU089VR588MGjHtNTTz0lV1xxhcybN0+SyaTMnTtXPvOZz0ipVFJxr43p7u5uueyyyySXy0lbW5vccsst4vu+ig2CQO666y5ZuXKlpFIp6ejokOuvv16GhoaO7cKRNw2cd2ceLgYMbrjhBvnmN78pH/rQh+Qb3/iG3HLLLZJOp2Xbtm2TMUNDQ3LJJZfImWeeKXfeeaesWLFCPve5z8nDDz981O37vi+XXHKJdHR0yFe+8hVZvXq13HrrrXLrrbe+kadFTmA2bNggzzzzjFx11VXyd3/3d3LDDTfIj3/8Y7nwwgun9Ct/YGBALr30Ulm1apXcddddctFFF03+244dO+QjH/mIXHrppXL77bdLLBaTK664Qh5//PHfus37779fisWi3HjjjXLPPffIunXr5J577pGrr74aYn3fl3Xr1klLS4vccccdsnbtWrnzzjvl29/+toq7/vrr5bOf/aycd955cvfdd8t1110n9913n6xbt05qtdoUrxZ5M8J59wQgJIrGxsbwE5/4xOv++9q1a0MRCb/zne9M9lUqlbCzszP80Ic+NNm3Z8+eUETCe++9d7LvmmuuCUUk/NSnPjXZFwRB+L73vS9MJBJhX1/f8T0ZclJQLBah79lnn4Vx9sQTT4QiEj7xxBOTfa+Nx29961uwjfnz54ciEj7wwAOTfSMjI+GsWbPCs84667du13ZMt99+e+g4Trhv377JvtfG9Be/+EUVe9ZZZ4WrV6+ebD/11FOhiIT33XefinvkkUes/SRacN6defhmwKBQKMhzzz0nhw4det2YXC4nH/vYxybbiURCzjnnHNm9e/eU9vHJT35y8r8dx5FPfvKTUq1WZf369cd+4OSkJZ1OT/53rVaTgYEBWbJkiRQKBXhNaiOZTMp1111n/beuri65/PLLJ9sNDQ1y9dVXy6ZNm6Snp2dKxzQxMSH9/f1y7rnnShiGsmnTJoi/4YYbVPuCCy5Qz8P9998vjY2NcvHFF0t/f//k/1avXi25XE6eeOKJo54nefPCeXfm4WLA4Ctf+Yq89NJLMnfuXDnnnHPktttug8E2Z84ccRxH9TU1NU0p9+m6rixatEj1LVu2TEQEcsQkGpRKJfnCF74gc+fOlWQyKa2trdLW1ibDw8MyMjJy1M/Pnj37df/CYMmSJTBWpzLe9u/fL9dee600NzdP6gDWrl0rIgLHlEqlpK2tTfWZz8OOHTtkZGRE2tvbpa2tTf1vfHxcent7j3qe5M0L592Zh39aaHDllVfKBRdcIA899JA89thj8tWvflX+1//6X/Lggw/KpZdeKiLyukrVkGIUcgx86lOfknvvvVduvvlmecc73iGNjY3iOI5cddVVEgTBUT//m7/ijwe+78vFF18sg4OD8rnPfU5WrFgh2WxWuru75dprr4VjmopyOwgCaW9vl/vuu8/67+ZigkQLzrszDxcDFmbNmiU33XST3HTTTdLb2ytnn322fPnLX54clL8LQRDI7t27J1elIiKvvvqqiPxa/U2ix3e/+1255ppr5M4775zsK5fLMjw8/Dtve+fOnRKGofpFdbTxtmXLFnn11Vfln//5n5Vg8Giiw9/G4sWLZf369XLeeecd98ULeXPAeXdmYZrgN/B9H16Btre3S1dXl1QqleO2n69//euT/x2GoXz961+XeDwu73rXu47bPsjJg+d58OvmnnvugT/NOxYOHTokDz300GR7dHRUvvOd78iqVauks7PzdY9HRP/iCsNQ7r777mM+jiuvvFJ835cvfelL8G/1ev24LHzIyQnn3RMDvhn4DcbGxmTOnDny4Q9/WM4880zJ5XKyfv162bBhg/rV9ruQSqXkkUcekWuuuUbe9ra3ycMPPyw//OEP5fOf/zxflUaU97///fIv//Iv0tjYKKeeeqo8++yzsn79emlpafmdt71s2TL5+Mc/Lhs2bJCOjg75x3/8Rzly5Ijce++9r/uZFStWyOLFi+WWW26R7u5uaWhokAceeOB38gNYu3atXH/99XL77bfL5s2b5T3veY/E43HZsWOH3H///XL33XfLhz/84WPePjl54bx7YsDFwG+QyWTkpptukscee0wefPBBCYJAlixZIt/4xjfkxhtvPC778DxPHnnkEbnxxhvls5/9rOTzebn11lvlC1/4wnHZPjn5uPvuu8XzPLnvvvukXC7LeeedJ+vXr5d169b9ztteunSp3HPPPfLZz35Wtm/fLgsXLpR/+7d/+63bjsfj8h//8R/y6U9/Wm6//XZJpVJy+eWXyyc/+Uk588wzj/lYvvWtb8nq1avl7//+7+Xzn/+8xGIxWbBggXzsYx+T884775i3S05uOO+eGDgh1RfTxrXXXivf/e53ZXx8fKYPhUSABQsWyGmnnSY/+MEPZvpQCJkxOO9ODWoGCCGEkIjDxQAhhBAScbgYIIQQQiIONQOEEEJIxOGbAUIIISTicDFACCGERBwuBgghhJCIM2XTIbNaFCHHwkxIVDh2yfHgRBm7N//lt1S7WitCTOjr33n1ag1iPvCB96r2o4/aSvnq/U9M4L7GxiegL5lKqXZToQAx9XpdtVcsXwoxe/bsV+10OoP7HxuFvve//92q/dTPnoWYzo4O1S6W8Ty2vLRVtXPZHMRccsklqv24pSTy7Nlzoa+xsV21X375RYhpbc+rdrWE4yGT1/d6aARtzL9228egz4RvBgghhJCIw8UAIYQQEnG4GCCEEEIizpQ1A0MjmJdxjHxSGGI+I/AD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TTfdJMuXL5d0Oi0tLS1yxRVXyN69e1WcLbd/4YUXymmnnSYbN26UNWvWSCaTkc9//vMiIrJgwQJ5//vfL4899pisWrVKUqmUnHrqqfLggw8e9ZieeuopueKKK2TevHmSTCZl7ty58pnPfEZKpZKKe+3Z6O7ulssuu0xyuZy0tbXJLbfcIr7vq9ggCOSuu+6SlStXSiqVko6ODrn++utlaGjo2C7cCQjTBP/Jli1b5D3veY+0tbXJbbfdJvV6XW699Vbp6OhQcV/+8pflL//yL+XKK6+UP/7jP5a+vj655557ZM2aNbJp06bJX2U/+clP5NJLL5XVq1fLrbfeKq7ryr333ivvfOc75amnnpJzzjlHbfeKK66QpUuXyt/8zd/AZEzI0bj++utl9uzZ8jd/8zfy6U9/Wt761rdKR0eH3HfffVKv12XdunVy/vnnyx133CGZTEbCMJQPfOAD8sQTT8jHP/5xWbVqlTz66KPy2c9+Vrq7u+VrX/va5LavvfZa+b//9//KH/3RH8nb3/52+elPfyrve9/7ZvBsyYnChg0b5JlnnpGrrrpK5syZI3v37pVvfvObcuGFF8rWrVslk8n81s8PDAzIpZdeKldddZV87GMfU/Ptjh075CMf+YjccMMNcs0118i9994rV1xxhTzyyCNy8cUXv+4277//fikWi3LjjTdKS0uLPP/883LPPffIwYMH5f7771exvu/LunXr5G1ve5vccccdsn79ernzzjtl8eLFcuONN07GXX/99fJP//RPct1118mnP/1p2bNnj3z961+XTZs2ydNPPy3xePwYr+AJREjCMAzDyy67LEylUuG+ffsm+7Zu3Rp6nhe+dpn27t0bep4XfvnLX1af3bJlSxiLxSb7gyAIly5dGq5bty4MgmAyrlgshgsXLgwvvvjiyb5bb701FJHwD/7gD97I0yMR4IknnghFJLz//vsn+6655ppQRML/8T/+h4r993//91BEwr/+679W/R/+8IdDx3HCnTt3hmEYhhs3bgxFJLz55ptV3LXXXhuKSHjrrbe+MSdDTgqKxSL0Pfvss6GIhN/5zncm+14bm0888cRk39q1a0MRCb/1rW/BNubPnx+KSPjAAw9M9o2MjISzZs0KzzrrrN+6Xdsx3X777aHjOGp+f+3Z+OIXv6hizzrrrHD16tWT7aeeeioUkfC+++5T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",
      "text/plain": [
       "<Figure size 640x480 with 6 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "import numpy as np\n",
    "\n",
    "# 从训练数据集的迭代器中获取一个批次的数据（字典形式）\n",
    "# create_dict_iterator()用于创建字典迭代器，next()获取下一个批次\n",
    "data_iter = next(dataset_train.create_dict_iterator())\n",
    "\n",
    "# 从数据字典中提取图像数据，并转换为numpy数组格式\n",
    "# asnumpy()是将框架张量（如PyTorch Tensor或MindSpore Tensor）转换为numpy数组\n",
    "images = data_iter[\"image\"].asnumpy()\n",
    "# 从数据字典中提取标签数据，并转换为numpy数组格式\n",
    "labels = data_iter[\"label\"].asnumpy()\n",
    "print(f\"Image shape: {images.shape}, Label shape: {labels.shape}\")\n",
    "\n",
    "# 训练数据集中，前六张图片所对应的标签\n",
    "print(f\"Labels: {labels[:6]}\")\n",
    "\n",
    "classes = []\n",
    "\n",
    "with open(data_dir + \"/batches.meta.txt\", \"r\") as f:\n",
    "    for line in f:\n",
    "        line = line.rstrip()\n",
    "        if line:\n",
    "            classes.append(line)\n",
    "\n",
    "# 训练数据集的前六张图片\n",
    "plt.figure()\n",
    "for i in range(6):\n",
    "    plt.subplot(2, 3, i + 1)\n",
    "    # 转换图像的维度顺序，通常原始图像格式为(C, H, W)，转换为(H, W, C)以便matplotlib显示\n",
    "    # (1, 2, 0)表示将第0维与第2维交换，得到正确的通道顺序\n",
    "    image_trans = np.transpose(images[i], (1, 2, 0))\n",
    "    mean = np.array([0.4914, 0.4822, 0.4465])\n",
    "    std = np.array([0.2023, 0.1994, 0.2010])\n",
    "    image_trans = std * image_trans + mean\n",
    "    image_trans = np.clip(image_trans, 0, 1)\n",
    "    plt.title(f\"{classes[labels[i]]}\")\n",
    "    plt.imshow(image_trans)\n",
    "    plt.axis(\"off\")\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "5bc7e066-ce5d-4a24-8e3e-a32991b15510",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "from typing import Type, Union, List, Optional\n",
    "import mindspore.nn as nn\n",
    "from mindspore.common.initializer import Normal\n",
    "\n",
    "# 初始化卷积层与BatchNorm的参数\n",
    "weight_init = Normal(mean=0, sigma=0.02)\n",
    "gamma_init = Normal(mean=1, sigma=0.02)\n",
    "\n",
    "class ResidualBlockBase(nn.Cell):\n",
    "    expansion: int = 1  # 最后一个卷积核数量与第一个卷积核数量相等\n",
    "\n",
    "    def __init__(self, in_channel: int, out_channel: int,\n",
    "                 stride: int = 1, norm: Optional[nn.Cell] = None,\n",
    "                 down_sample: Optional[nn.Cell] = None) -> None:\n",
    "        super(ResidualBlockBase, self).__init__()\n",
    "        if not norm:\n",
    "            self.norm = nn.BatchNorm2d(out_channel)\n",
    "        else:\n",
    "            self.norm = norm\n",
    "\n",
    "        self.conv1 = nn.Conv2d(in_channel, out_channel,\n",
    "                               kernel_size=3, stride=stride,\n",
    "                               weight_init=weight_init)\n",
    "        self.conv2 = nn.Conv2d(in_channel, out_channel,\n",
    "                               kernel_size=3, weight_init=weight_init)\n",
    "        self.relu = nn.ReLU()\n",
    "        self.down_sample = down_sample\n",
    "\n",
    "    def construct(self, x):\n",
    "        \"\"\"ResidualBlockBase construct.\"\"\"\n",
    "        identity = x  # shortcuts分支\n",
    "\n",
    "        out = self.conv1(x)  # 主分支第一层：3*3卷积层\n",
    "        out = self.norm(out)\n",
    "        out = self.relu(out)\n",
    "        out = self.conv2(out)  # 主分支第二层：3*3卷积层\n",
    "        out = self.norm(out)\n",
    "\n",
    "        if self.down_sample is not None:\n",
    "            identity = self.down_sample(x)\n",
    "        out += identity  # 输出为主分支与shortcuts之和\n",
    "        out = self.relu(out)\n",
    "\n",
    "        return out"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "5953a980-1b18-4a3b-aed2-1e6ec0405300",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "class ResidualBlock(nn.Cell):\n",
    "    expansion = 4  # 最后一个卷积核的数量是第一个卷积核数量的4倍\n",
    "\n",
    "    def __init__(self, in_channel: int, out_channel: int,\n",
    "                 stride: int = 1, down_sample: Optional[nn.Cell] = None) -> None:\n",
    "        super(ResidualBlock, self).__init__()\n",
    "\n",
    "        self.conv1 = nn.Conv2d(in_channel, out_channel,\n",
    "                               kernel_size=1, weight_init=weight_init)\n",
    "        self.norm1 = nn.BatchNorm2d(out_channel)\n",
    "        self.conv2 = nn.Conv2d(out_channel, out_channel,\n",
    "                               kernel_size=3, stride=stride,\n",
    "                               weight_init=weight_init)\n",
    "        self.norm2 = nn.BatchNorm2d(out_channel)\n",
    "        self.conv3 = nn.Conv2d(out_channel, out_channel * self.expansion,\n",
    "                               kernel_size=1, weight_init=weight_init)\n",
    "        self.norm3 = nn.BatchNorm2d(out_channel * self.expansion)\n",
    "\n",
    "        self.relu = nn.ReLU()\n",
    "        self.down_sample = down_sample\n",
    "\n",
    "    def construct(self, x):\n",
    "\n",
    "        identity = x  # shortcuts分支\n",
    "\n",
    "        out = self.conv1(x)  # 主分支第一层：1*1卷积层\n",
    "        out = self.norm1(out)\n",
    "        out = self.relu(out)\n",
    "        out = self.conv2(out)  # 主分支第二层：3*3卷积层\n",
    "        out = self.norm2(out)\n",
    "        out = self.relu(out)\n",
    "        out = self.conv3(out)  # 主分支第三层：1*1卷积层\n",
    "        out = self.norm3(out)\n",
    "\n",
    "        if self.down_sample is not None:\n",
    "            identity = self.down_sample(x)\n",
    "\n",
    "        out += identity  # 输出为主分支与shortcuts之和\n",
    "        out = self.relu(out)\n",
    "\n",
    "        return out"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "a53c60de-974f-4bc0-88b6-9268b32424d9",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "def make_layer(last_out_channel, block: Type[Union[ResidualBlockBase, ResidualBlock]],\n",
    "               channel: int, block_nums: int, stride: int = 1):\n",
    "    down_sample = None  # shortcuts分支\n",
    "\n",
    "    if stride != 1 or last_out_channel != channel * block.expansion:\n",
    "\n",
    "        down_sample = nn.SequentialCell([\n",
    "            nn.Conv2d(last_out_channel, channel * block.expansion,\n",
    "                      kernel_size=1, stride=stride, weight_init=weight_init),\n",
    "            nn.BatchNorm2d(channel * block.expansion, gamma_init=gamma_init)\n",
    "        ])\n",
    "\n",
    "    layers = []\n",
    "    layers.append(block(last_out_channel, channel, stride=stride, down_sample=down_sample))\n",
    "\n",
    "    in_channel = channel * block.expansion\n",
    "    # 堆叠残差网络\n",
    "    for _ in range(1, block_nums):\n",
    "\n",
    "        layers.append(block(in_channel, channel))\n",
    "\n",
    "    return nn.SequentialCell(layers)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "178e32bb-a88e-4c4a-9ee8-0d249f38c965",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "from mindspore import load_checkpoint, load_param_into_net\n",
    "\n",
    "\n",
    "class ResNet(nn.Cell):\n",
    "    def __init__(self, block: Type[Union[ResidualBlockBase, ResidualBlock]],\n",
    "                 layer_nums: List[int], num_classes: int, input_channel: int) -> None:\n",
    "        super(ResNet, self).__init__()\n",
    "\n",
    "        self.relu = nn.ReLU()\n",
    "        # 第一个卷积层，输入channel为3（彩色图像），输出channel为64\n",
    "        self.conv1 = nn.Conv2d(3, 64, kernel_size=7, stride=2, weight_init=weight_init)\n",
    "        self.norm = nn.BatchNorm2d(64)\n",
    "        # 最大池化层，缩小图片的尺寸\n",
    "        self.max_pool = nn.MaxPool2d(kernel_size=3, stride=2, pad_mode='same')\n",
    "        # 各个残差网络结构块定义\n",
    "        self.layer1 = make_layer(64, block, 64, layer_nums[0])\n",
    "        self.layer2 = make_layer(64 * block.expansion, block, 128, layer_nums[1], stride=2)\n",
    "        self.layer3 = make_layer(128 * block.expansion, block, 256, layer_nums[2], stride=2)\n",
    "        self.layer4 = make_layer(256 * block.expansion, block, 512, layer_nums[3], stride=2)\n",
    "        # 平均池化层\n",
    "        self.avg_pool = nn.AvgPool2d()\n",
    "        # flattern层\n",
    "        self.flatten = nn.Flatten()\n",
    "        # 全连接层\n",
    "        self.fc = nn.Dense(in_channels=input_channel, out_channels=num_classes)\n",
    "\n",
    "    def construct(self, x):\n",
    "\n",
    "        x = self.conv1(x)\n",
    "        x = self.norm(x)\n",
    "        x = self.relu(x)\n",
    "        x = self.max_pool(x)\n",
    "\n",
    "        x = self.layer1(x)\n",
    "        x = self.layer2(x)\n",
    "        x = self.layer3(x)\n",
    "        x = self.layer4(x)\n",
    "\n",
    "        x = self.avg_pool(x)\n",
    "        x = self.flatten(x)\n",
    "        x = self.fc(x)\n",
    "\n",
    "        return x"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "3cd6a7e5-2e8d-48bb-a8ed-c92b50c1fb95",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "def _resnet(model_url: str, block: Type[Union[ResidualBlockBase, ResidualBlock]],\n",
    "            layers: List[int], num_classes: int, pretrained: bool, pretrained_ckpt: str,\n",
    "            input_channel: int):\n",
    "    model = ResNet(block, layers, num_classes, input_channel)\n",
    "\n",
    "    if pretrained:\n",
    "        # 加载预训练模型\n",
    "        download(url=model_url, path=pretrained_ckpt, replace=True)\n",
    "        param_dict = load_checkpoint(pretrained_ckpt)\n",
    "        load_param_into_net(model, param_dict)\n",
    "\n",
    "    return model\n",
    "\n",
    "\n",
    "def resnet50(num_classes: int = 1000, pretrained: bool = False):\n",
    "    \"\"\"ResNet50模型\"\"\"\n",
    "    resnet50_url = \"https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/notebook/models/application/resnet50_224_new.ckpt\"\n",
    "    resnet50_ckpt = \"./LoadPretrainedModel/resnet50_224_new.ckpt\"\n",
    "    return _resnet(resnet50_url, ResidualBlock, [3, 4, 6, 3], num_classes,\n",
    "                   pretrained, resnet50_ckpt, 2048)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "2abdcdf8-dfab-44ad-8ec8-3d58d6426fbf",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Downloading data from https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/notebook/models/application/resnet50_224_new.ckpt (97.7 MB)\n",
      "\n",
      "file_sizes: 100%|█████████████████████████████| 102M/102M [00:00<00:00, 250MB/s]\n",
      "Successfully downloaded file to ./LoadPretrainedModel/resnet50_224_new.ckpt\n"
     ]
    }
   ],
   "source": [
    "# 定义ResNet50网络\n",
    "network = resnet50(pretrained=True)\n",
    "\n",
    "# 全连接层输入层的大小\n",
    "in_channel = network.fc.in_channels\n",
    "fc = nn.Dense(in_channels=in_channel, out_channels=10)\n",
    "# 重置全连接层\n",
    "network.fc = fc"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "3a552eb4-9e5c-436b-be10-54dcd7d1fd87",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "# 设置学习率\n",
    "num_epochs = 5\n",
    "lr = nn.cosine_decay_lr(min_lr=0.00001, max_lr=0.001, total_step=step_size_train * num_epochs,\n",
    "                        step_per_epoch=step_size_train, decay_epoch=num_epochs)\n",
    "# 定义优化器和损失函数\n",
    "opt = nn.Momentum(params=network.trainable_params(), learning_rate=lr, momentum=0.9)\n",
    "loss_fn = nn.SoftmaxCrossEntropyWithLogits(sparse=True, reduction='mean')\n",
    "\n",
    "\n",
    "def forward_fn(inputs, targets):\n",
    "    logits = network(inputs)\n",
    "    loss = loss_fn(logits, targets)\n",
    "    return loss\n",
    "\n",
    "\n",
    "grad_fn = ms.value_and_grad(forward_fn, None, opt.parameters)\n",
    "\n",
    "\n",
    "def train_step(inputs, targets):\n",
    "    loss, grads = grad_fn(inputs, targets)  # 计算损失和参数梯度\n",
    "    opt(grads)  # 使用优化器根据梯度更新网络参数\n",
    "    return loss"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "a4aadb85-91bc-42f6-ac8e-3c6933a90b27",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "import os\n",
    "\n",
    "# 创建迭代器\n",
    "data_loader_train = dataset_train.create_tuple_iterator(num_epochs=num_epochs)\n",
    "data_loader_val = dataset_val.create_tuple_iterator(num_epochs=num_epochs)\n",
    "\n",
    "# 最佳模型存储路径\n",
    "best_acc = 0\n",
    "best_ckpt_dir = \"./BestCheckpoint\"\n",
    "best_ckpt_path = \"./BestCheckpoint/resnet50-best.ckpt\"\n",
    "\n",
    "if not os.path.exists(best_ckpt_dir):\n",
    "    os.mkdir(best_ckpt_dir)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "0fa8f81c-e29d-45f7-a2a1-83599cbfe168",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "import mindspore.ops as ops\n",
    "\n",
    "\n",
    "def train(data_loader, epoch):\n",
    "    \"\"\"模型训练\"\"\"\n",
    "    losses = []  # 用于存储每一步训练的损失值\n",
    "    network.set_train(True)  # 将网络设置为训练模式，启用 dropout、批量归一化等训练特定操作\n",
    "\n",
    "    for i, (images, labels) in enumerate(data_loader):\n",
    "        loss = train_step(images, labels)\n",
    "        # 每100步或到达本轮最后一步时打印训练信息\n",
    "        if i % 100 == 0 or i == step_size_train - 1:\n",
    "            print('Epoch: [%3d/%3d], Steps: [%3d/%3d], Train Loss: [%5.3f]' %\n",
    "                  (epoch + 1, num_epochs, i + 1, step_size_train, loss))\n",
    "        losses.append(loss)  # 将当前批次的损失值添加到损失列表中\n",
    "\n",
    "    return sum(losses) / len(losses)\n",
    "\n",
    "\n",
    "def evaluate(data_loader):\n",
    "    \"\"\"模型验证\"\"\"\n",
    "    network.set_train(False)\n",
    "\n",
    "    correct_num = 0.0  # 预测正确个数\n",
    "    total_num = 0.0  # 预测总数\n",
    "\n",
    "    for images, labels in data_loader:\n",
    "        logits = network(images)\n",
    "        pred = logits.argmax(axis=1)  # 预测结果\n",
    "        # 比较预测结果与真实标签，返回布尔值张量；reshape((-1,))将张量展平为一维\n",
    "        correct = ops.equal(pred, labels).reshape((-1, ))\n",
    "        correct_num += correct.sum().asnumpy()\n",
    "        total_num += correct.shape[0]\n",
    "\n",
    "    acc = correct_num / total_num  # 计算整体准确率（正确数/总数）\n",
    "\n",
    "    return acc  # 返回验证集上的准确率"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "339897a8-caf6-4d60-93ab-471eb88719dd",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Start Training Loop ...\n",
      "Epoch: [  1/  5], Steps: [  1/196], Train Loss: [2.352]\n",
      "Epoch: [  1/  5], Steps: [101/196], Train Loss: [1.469]\n",
      "Epoch: [  1/  5], Steps: [196/196], Train Loss: [1.172]\n",
      "--------------------------------------------------\n",
      "Epoch: [  1/  5], Average Train Loss: [1.627], Accuracy: [0.601]\n",
      "--------------------------------------------------\n",
      "Epoch: [  2/  5], Steps: [  1/196], Train Loss: [1.166]\n",
      "Epoch: [  2/  5], Steps: [101/196], Train Loss: [0.875]\n",
      "Epoch: [  2/  5], Steps: [196/196], Train Loss: [0.888]\n",
      "--------------------------------------------------\n",
      "Epoch: [  2/  5], Average Train Loss: [1.002], Accuracy: [0.687]\n",
      "--------------------------------------------------\n",
      "Epoch: [  3/  5], Steps: [  1/196], Train Loss: [0.897]\n",
      "Epoch: [  3/  5], Steps: [101/196], Train Loss: [0.872]\n",
      "Epoch: [  3/  5], Steps: [196/196], Train Loss: [0.933]\n",
      "--------------------------------------------------\n",
      "Epoch: [  3/  5], Average Train Loss: [0.837], Accuracy: [0.718]\n",
      "--------------------------------------------------\n",
      "Epoch: [  4/  5], Steps: [  1/196], Train Loss: [0.807]\n",
      "Epoch: [  4/  5], Steps: [101/196], Train Loss: [0.791]\n",
      "Epoch: [  4/  5], Steps: [196/196], Train Loss: [0.565]\n",
      "--------------------------------------------------\n",
      "Epoch: [  4/  5], Average Train Loss: [0.764], Accuracy: [0.738]\n",
      "--------------------------------------------------\n",
      "Epoch: [  5/  5], Steps: [  1/196], Train Loss: [0.758]\n",
      "Epoch: [  5/  5], Steps: [101/196], Train Loss: [0.866]\n",
      "Epoch: [  5/  5], Steps: [196/196], Train Loss: [0.688]\n",
      "--------------------------------------------------\n",
      "Epoch: [  5/  5], Average Train Loss: [0.735], Accuracy: [0.741]\n",
      "--------------------------------------------------\n",
      "================================================================================\n",
      "End of validation the best Accuracy is:  0.741, save the best ckpt file in ./BestCheckpoint/resnet50-best.ckpt\n"
     ]
    }
   ],
   "source": [
    "# 开始循环训练\n",
    "print(\"Start Training Loop ...\")\n",
    "\n",
    "for epoch in range(num_epochs):\n",
    "    curr_loss = train(data_loader_train, epoch)\n",
    "    curr_acc = evaluate(data_loader_val)\n",
    "\n",
    "    print(\"-\" * 50)\n",
    "    print(\"Epoch: [%3d/%3d], Average Train Loss: [%5.3f], Accuracy: [%5.3f]\" % (\n",
    "        epoch+1, num_epochs, curr_loss, curr_acc\n",
    "    ))\n",
    "    print(\"-\" * 50)\n",
    "\n",
    "    # 保存当前预测准确率最高的模型\n",
    "    if curr_acc > best_acc:\n",
    "        best_acc = curr_acc\n",
    "        ms.save_checkpoint(network, best_ckpt_path)\n",
    "\n",
    "print(\"=\" * 80)\n",
    "print(f\"End of validation the best Accuracy is: {best_acc: 5.3f}, \"\n",
    "      f\"save the best ckpt file in {best_ckpt_path}\", flush=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "7a4a00c0-4811-447e-9b37-cd3a03855b52",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAgMAAAGFCAYAAABg2vAPAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuNCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8ekN5oAAAACXBIWXMAAA9hAAAPYQGoP6dpAABvsUlEQVR4nO29eZRlZ1nv/+y9z3xqODV2V89Tkk5nhISATIEAEhC4KIPIVUEBUZn0qvfq1SW48Cd6UURwxN8FBLzIEEVEZLpEmQnpzJ100t3pubqru4ZTVWc+e+/398f+1ao8Q7oObSdVnf39rJWVvG+es8d3v+et/XzP9/Gcc44AAAAAkFr81T4AAAAAAKwuWAwAAAAAKQeLAQAAACDlYDEAAAAApBwsBgAAAICUg8UAAAAAkHKwGAAAAABSDhYDAAAAQMrBYgAAAABIOVgMGPz7vxN5XvLvJV7/eqJt21bneIiInvOc5B8AemYtDmQAegFj93EHi4HHmD/4A6LPfW61jwKA/ySrOZC/8x2id72LqFpdnf2DixuM3Z7AYqBH/vZviR588If/HBYDYE1xMQ7k73yH6Pd+76KYUMFjCMbuY0pmtQ/gQhLHRJ0OUaFw4bedzV74bQJggoEMLlYwdi9a1uSbgXe9K0kX7d9P9OpXEw0MEI2MEL3jHUSt1nKc5xG99a1Ef//3RFdcQZTPE33pS8n/O3mS6Od/nmjduqT/iiuIPvxhva8TJ4he/nKicplofJzoV3+VqN3WcVa6Ko6J/uzPiK66Khn7Y2NEN99MdPvty8dXrxP93d8l/+15yXaW2L+f6Ngxva8PfYho506iYpHohhuIvvlN+zqdOUP0hjck51goEF1zTbIvycwM0c/8THIdKxWi172O6O67k+P56EftbYMLQNoH8ve/T/TiFxMNDSXHdfXVyX6WuOeeZDs7diT7Xb8+OdeZGX4Nf+M3kv/evn15/0eO6P2BCwfGburG7pp+M/DqVyf3/j3vIfre94g+8AGiuTmij31sOebrXyf69KeT8Tg6msRPTRE97WnL43RsjOjf/i354lxYIPqVX0k+22wSPe95yVh4+9uJNmwg+vjHk232whvekHyZvuhFRG98I1EYJl/c3/se0fXXJ9t64xuTL/Rf+IXkMzt3Ln/+8suJbryRa2T+9/8mevObiZ7+9OQ4H36Y6GUvIxoeJtq8eTmu2UwEhQcPJue4fTvRZz6TjM9qNXlmiZJn5aUvJbrtNqJf+iWi3buJ/vmfkwUBeJxI40D+6leJXvISoomJZDCuX0/0wANEX/jC8uD86leTAf5zP5f8/337kpXwvn3Jvj2P6Cd+guihh4g++UmiP/3T5NoQJdcCPPZg7KZn7Lo1yDvf6RyRcy97Ge//5V9O+u++O2kTOef7zu3bx+Pe8AbnJiacm57m/a95jXODg841Gkn7/e9PtvHpTy/H1OvO7dqV9N9663L/617n3Naty+2vfz2Jefvb9fHH8fJ/l8vJZy2InLvxxuV2p+Pc+Lhz117rXLu93P+hD+nYpWP/xCf453/kR5zr63NuYSHpu+WWJO7971+OiyLnbrop6f/IR+xjAxeAtA7kMHRu+/ZkP3Nzj77NpeN/JJ/8ZLK9b3xjue+97036Dh+29w8uPBi7qRu7azJNsMRb3sLbb3tb8u8vfnG578YbifbsWW47R3TLLclfw84RTU8v//PCFxLNzxPdccfydiYmiF75yuXPl0rLC8hzccstyeLvne/U/8/zejs/5/iC9Pbbk1f/v/iLRLnccv/rX080OMg/+8UvJgvSn/qp5b5sNllc12pE//EfSd+XvpT0v+lNy3G+r68teAxJ20C+806iw4eTv/4qlUffZrG4/N+tVnJuT3ta0l46N7C6YOza23wCjt01nSa45BLe3rkz+SJ7ZMpl+3Yec/Zs8pr8Qx9K/rE4cyb599GjRLt26XFz2WUrH9uhQ8kbreHhlWN75ejR5N/yvLPZJDUlYy+5JLkej+Tyy/m2jh5NnrVSicft2nVhjhn0QNoG8qFDyb+vvPLccbOzidL6H/5h+VyWmJ+/cMcDzh+MXZsn4Nhd04sBibXYe+QCjSjJkRMR/fRPP3pe/OqrL+xxAfBDgYGc8OpXJz+9+o3fILr2WqK+vuS8b755+fzB2gJjN+EJOHbX9GLgwAG+6Dx4MLnO5zKhGhsj6u8niiKi5z//3NvfupXovvuSN0WPHOO9/JR1506iL385WSCea2Ha69uqpeMhSs77ppuW+7vd5M3VNdfw2HvuSa7HI98O7N/Pt7V1K9GttxI1GvztwMGDvR8X+E+StoG8JNC6775HP/a5OaL/+3+Tv65+93eX+w8c+M/tG1xYMHY1T9Cxu6Y1A3/xF7z9wQ8m/37Rix79M0FA9IpXJOmk++7T///s2eX/fvGLiSYniT772eW+RuPR32w9kle8Ihm/v/d7+v85t/zf5fKj+03IX7Vcf33yHP31Xyc/1V3iox/V23jxi4lOnyb61KeW+8IwuUZ9fUkajyhJ0XW7iV/HEnGsry14DEnbQH7yk5MvkPe/X39maZtBoPdBlHxGUi4n/74IjFuecGDs6m0+Qcfumn4zcPhw8rO6m28m+u53iT7xCaLXvpb/hWzxh3+Y/DX81Kcmwrk9e5LF4x13EH3ta8l/EyX/78//nOhnf5Zo794kt/7xj+v8usVzn5v8dv8DH0gWhEtvh775zeT/vfWtSdx11yX7fN/7kvTW9u3JcRHpX7Vks0S///vJTwtvuonoJ38yuQYf+YjWDPzCLxD9zd8k4sK9e5OF+mc/S/Ttbydjsr8/iXv5y5Nf1fzaryWL+t27iT7/+eVrcBEtXC9e0jaQfZ/or/4qEZBde23y86uJiWTi3bcv+WtuYIDo2c8m+l//K1mtbtxI9JWvJNdKct11yb9/+7eJXvOa5EF56UuXJ1rw2IGxm56xu9o/Z7BY+lXL/fc798pXOtff79zQkHNvfatzzeZyHJFzb3mLvY2pqeT/bd7sXDbr3Pr1zj3vecnP9B7J0aPJr2dKJedGR517xzuc+9KXVv5Vi3PJr1De+17ndu92LpdzbmzMuRe9yLm9e5dj9u937tnPdq5YTLb5yF+4yF+1LPGXf5n8uiWfd+7665Nfqtx4o46dmnLu534uOe5czrmrrrJ/Knj2rHOvfW1yHQcHnXv965379reT/f/DP9jXD1wA0j6Qv/Ut517wguS8y2Xnrr7auQ9+cPn/nzjh3I//uHOVSjIwX/Uq5yYnk+298518W+9+t3MbNyY/Y7tIfqp1UYOxm7qx6zkn33WsPu96V/Lm5+zZZZ8GcGH53OeIfvzHib71LaJnPGO1j+YJCgYyuFjB2E0da1ozAC4MzSZvR1GS+hsYSFJkAAAA0s2a1gyAC8Pb3pYsCH7kRxLL73/8x+RXMX/wB/pXQQAAANIHFgMp4KabiP7kTxJr7VYr8fj44AeX9TUAAADSzZrUDAAAAADg8QOaAQAAACDlYDEAAAAApBwsBgAAAICU07OA8D++9hnVFzfrrF3KjamYoMQt7rpxR8V4uT6+nX7LZ5oXf+jUqioi19+n+op9vPZvt97SWxaFJYJSQcU4x2PidlvFZDP6cjrikgy5HSKisBPxmK6OKfXxbccuUjGtRsjahWK/iulEXdUXid1l8vr8Q8fvY6cTqpg4FOcaaznK0667VvU91gwOVlRfFOnrJ5H3yvP02tn3+XWJIn3OhUKOtYcGtLva+hF9jOPj61j75OkzKubQsUnW7rT180W0yrKg87G5XINSpoXFxcd9n//+7e+qvliNy/Pbtp6LrGsunxPjubE+5p2zafdZ2xHjwDOCepG9OafnvWyWz3OFvPZT8MRResbFlnu3T8PolX1mCO+U956IKBZzmbWrZzzzBuOoOHgzAAAAAKQcLAYAAACAlIPFAAAAAJByetYMOC9QffUmz0/mszqf0lfieev6zEm97Q5PcpT6h1SM54ucuacPPTRy7TLFEmT1eUQtnv/3OkZeP5R5Gb2dTmzlc/i55Qs6X9ztVEW7pmKKZX5NPNL79wOex++GTRVDmazqkrqGVkfnnYNcXnQY68iQn38UaV3BxYxvJD6ljsDzdU7V8/j1LRT1PcjldF+ny8dlFOu8p9w2yTbRqksGzgsrEX6eOgJDunLRYOXI1ZPXg2bAylmfn9ZAP/e9bKcnzYAVJCfw876X1nHzOVTqf6wY8xBlXt+IkdqDpFNqBvTJya8U39qOz8/tfK2D8GYAAAAASDlYDAAAAAApB4sBAAAAIOX0rBkolPVv1j2RRw+yOR0jctT9ZV0mryNSoVYOKiO2XR7QuoI41vnabpdvPGvoGvxA5LrrRs6+xHP9cVbneBcW6qrP9/hxZzN5FdPXx/0Rwq7Otevft+rzyGT52q4Tai8E39f3SK4Jo1BnveTe/IzWLHjysN3FXQcr8KUewDhnkWf0jXSdJzr7+8oqZtv2LaqvG/KxOz03q2Kc9bvvC8X5/oD9QnABfQYsrcdKrBWdQWT4gsTyt/fxyvno3vLIeiwZWWy9K2NL6vf5VozcuJ2QF+3exrv6mPE5P+B9kaH56mXoaC8ZO0p3rezL0ovPgIwxQnoCbwYAAACAlIPFAAAAAJBysBgAAAAAUg4WAwAAAEDK6Vnh5We08KzcP8BjYi0OrDd5YaCMoa4o5Pi2ZeEFIqKOECta5gvdthbeuS430HFlfcqN2jxrt85MqZj+YX6umaEBFZPPa1FhEAjRmWcY+mRFESRDyNJqcQOhfF6bF0nlSGQUhbKNNYRQzhCydISYLTDMi6TI0Srq8cTHUO8IpVQmp9fgxZIWlrqGEOhm9Oek95NVwMo3DKrAuVHP7SoRW4V5enHeOQ8VmSkyVCo/63iM4j1iW9ZfnWp/1u57mkJ6OW4LeY0McV4PEsLzNflRV9by2TqPDZ2v9hVvBgAAAICUg8UAAAAAkHKwGAAAAABSTu+FijJGjloY+rRa8yokEjnqkXKfipmrc7Oert9QMZUhrkfIWWmirjYLatW4UcvxhyZVTHWa97mWNg/KCJ+Y3IA2jplYd7nqG12/i7UbLUszIIxrVITO/zsyDJ5EUY2MX9D7io2ti2uZMY6g2+F6jKxlXiTSrIFh0rMauPN14Ti/vRn7F0WuIqsQlta7yD47fyo6rVyp/KA1BozcaCy0I5beRBnVmPnT8xkHj6GZUg9Iw6nVQt6DBFk0zfqkO0crQd5NZ+ldZB0sr8dnyQkjM2v/6rlcuciWncG3jkkm0q0iduI6Glot+ez0og8wpRfGw6vMgqwPqpgVD5Fa4flptdbGiAcAAADAqoHFAAAAAJBysBgAAAAAUg4WAwAAAEDK+SHKymnBWLvDBReOdIWtQoFXO8zltbmK3+LGRLLKGxFRNiv62k0VM3XygOo7evB+1l6oTquYsM2Fh8WiFjz1tfilqk1pIWD1yAnVt2HnGdYe2nqliikPj/MO665EXEzmrAp6Ab9HgSGskUJAa1uerw8gEO42znDIUEK9i9xzSGq3LBmcXE3HlgGLuCxW5bHYEBX2VDlPiPqs7cjqbOTp+5vN6ucyEgfQaWthL4ln3hIZ+ko81cvfIGYJux4+d2GwKtitDpYgtYeYngx15Hb1dqTwzTY8stxyxP6sbavjWfma++b+V642aFUtlNUfbaFxL6ZDK3/Gura9CAi1MZOOkc/p6dr5VYvFmwEAAAAg5WAxAAAAAKQcLAYAAACAlNNzciEXGKGiWE5Q0HlHWe+j09W5/nKRf65gFPzpNqqsff/9d6mYIw/cq/o6Da4HCDstFeNEEZ7QyEH5oTD06Wp9RD0+pPoOd7mBUbF/QsUMDW9m7a5h7OFn+bqt2dH7z2b5MUZG7qoTtlVfJs/Niay8YEYUyYlirT2gNZNnXdt4Pa7BZa49MJ7B8XGuN7n0kkEVMznJTbXOTlVVTH9/RfWVStxYK471mGsJvU21OqdiQvF8+eb5r62/SzzTYOnxJzbmIpnr9sxcu9RzWbqClXuUMVDco5ZDml8ZGiOtGehBD2DufmXNgGdsW2p3YmfMaeq4Vz5/S09lOoZJzYAhEpKaAes8Ftt82ydm9HdsL6ytJxAAAAAAjztYDAAAAAApB4sBAAAAIOVgMQAAAACknN4FhIYRTVzgFQijSJuSZDwuHvKMimlxhxtCzM2eVTGnzhxn7fsf2Ktiui29/0CIOcK2IdIIhThPa+yo7fHOEhlBRp8LZlh79vh9KmZ4ZIi1C2PjKkb6MC00dYXGQJrkGJqVjNPikqwQrsSetteJPX6NTPOPqJcKdo8/nqfHnO/98FXxzEp2siBgLyYxxn2JDfFlFPJjDCMtcBobHWHtZz7j6Sqmtsirid5z5z4V02rr69Fs8udp06atKmbd+mHWvnefHt8PHeDC2nZbCxF9dY+s6pqW7VMvQr8ffhyulaqFYaSvlRSVmVpHKU6zYkSfZXqjnnPTc8iqtifHs76eUmhnmQ55YtumEZfx7MhrYgkxPWlE5GljvUBUZ7WrFvJtR4bIMo6N+Ubs35qn5KWNDLHk6QYXgM8szqqYXlgbIx4AAAAAqwYWAwAAAEDKwWIAAAAASDk9awbaTZ1r9oTJUFZ7BVEQ89z2ycNTKuYr//p11p6Z0zmPyig3QGm5Rb0vI8/nRTzPGIc6L+TCjGjrvEzT5/nTeU9fj1yoc5rlkMfNnLxLxXTdAmsPb7texWzbuoO1+/VpkBdzQyVnGANlLK1Dl38uMkryxJFMXulrFMiE3hrRDPSEZQpyHvi95LCNvJ9lONLp8HvVqNdVTK3Fc8pHjmjjq/WjXJNyyS6d+z9x/JTq67b4M9aoVVXMQN9G1n7Jj71Axdz/4DbWvuvue1TMqZN8Xgi7hpGOoWUh18vfM3JbK49L3zJZWwVMcy+B68EIpzevHquYEb++lukNkaW/Wfka60JJxv57MFgyDYVEWODrL6e+PNdmlQrasEseUqutTbW6IZ8/fVN7oMdTJDUTZjEnfv8bHT3eZxv8+ncaCyqmF/BmAAAAAEg5WAwAAAAAKQeLAQAAACDlYDEAAAAApJyeVTJ1YVxCRFTMcGFSkNGbe2DfMdb+m7/8GxVz5+23s/aPPOVJKqY0wEVPkSEIcZHev+eEmMMQBnWF8C5y2rzIl4Imy2ejqzvrbb6tYk4L+KKow9rHTmrTpVL2xaw9OLJRxYSiIqQfdlSMF+pzk9XCYl8LtaT5hSVmkyY5pUJBxaxZLLGjFBX2ojE0jEMCWbrTiOkYhkL1Br/GzZa+n21xj09PGkJAIShqN/V2LFHj4ACvStpuadHumSleEXHnJVqceNNNz2Lt4eGKivnKV25l7ZMn9DPQWyHBCyQEXSPiV2cY6shDM4aTrghoGQOt+Cld2c+sbNiDgZdt1nMe19jYl2XYlQ343NNfHNXbivi831jU4vZGi8+pc7PHdEyDG8vl83reqwxtVn1BtsLamayu+hsLo63TTS1OnFuosnZTtHsFbwYAAACAlIPFAAAAAJBysBgAAAAAUg4WAwAAAEDK6VlAGBoCkFC4pnWMioC33fEga584qx2cLr3ictaujGknqEi4XMWmy1NZ9ZHHRRkdY/3TjkRlQ8OlzxfFw1xHi1baHS2qaxIX7FXyfSqmMsCPqbZwQsUc2Hcna1/15JKKCaRzYKTPI+xoEVhLON15hhDUy/BjdKHe9lyVi0w7ZeN+rALOqBgWGaKjlcgY4lMpmvWNUpHFEh+D1p5bhtiz0eF9nlF6rj/Pr3Eh06/3X+R9lYrezrrxIdXX3ycEhIbwMBvwcysGWtg7NDDA2nsuvUTF7Lv7ftY+PakFhLZDnrwnloBQCjgt9a+suLmy89/jgZOVQIkolq58xoCSZqye4bBpi/pEjLqeK7sd2n2WQFc6lq78t6nvr+xSSESUy3ARn3Ud64t8jFXnplVMsyuq7ma0uLrR4C67YagrTYbhcdUX02nW7h/ermIWaD1rTy7obc9XuYCxvlhVMb2ANwMAAABAysFiAAAAAEg5WAwAAAAAKadnzUDLyFdGHZ5XCw3viWc893ms/ZybblQxYZNXKfzeN76uYuZr3DglZ+TeKdA56lqL55NasWGs4fHcaOjrfKE06wmMlKKVU+3GPLc+V9S5/vGI511dqLUHD+/jld7GBwdUzMaNG1g7djq/FBm5/laL7y+U+VMilYTsGjn3wOfXul7TlR3XCp7l1CKIxXUIDWOgbI5rV4KsUfFR5DQbhnlQrd5Sfc0mv1fS1ImIqJzj51EqaeOS4RGuwenr03n9S3dtUX0bJtaxdjFfVDG5DO9rtgydinjkymU9dnft2snad929T2/HKmToycpvOkamuXvKeq8NzyE1Bom0yY5vVHM0pusVt2NXzZMXz6gMaxoarazJkdUGLfMgeSOcoeXwLT2ECJub1zn7pjDjOnz4QRUTCI3AyHpt9kYe1yd09bRL7bo2A/Oz/NkJg2EVM0sV1l405tTmItfhtQxzsF7AmwEAAAAg5WAxAAAAAKQcLAYAAACAlIPFAAAAAJByehYQNps11eeEWKpjKHwGK1zoNzKkhX8P3c/NH0JD4pMVgkEvq7czs6gr8s0ucsFFHGgRVLHARX2ZfEXFRA0psltQMd1QC2miNleTzLX0+uvh0/wY+/JaCNla5CLL+/Z+R8WUctezdjavhWKtphZ4eQE/psgw6emKvrl5ff7ZHD/uymBFxawVeqmAZwmzJGHE72+Q0wK+jKha2GpqhdHsjK4KOj/Px5yleRwa5YZCY+u06VCpj+/fD/Rzat7zLhc6BsZF84RQrNHSz2BHmHoVilpAeP31fOx++7u3q5ijR7UISxaEtFE1/Fb8hBR9rhaxcV/koTlDrNeLp1ZPpkMyxhgDfk9qy/OLkVUTCxn9fPUVKvpzQtweOy3aPfrwAdb+6q3fUDET68dY++pIC33LlRHWjoy/sc+e0tUOpTFUJdbnFuW5QLmxoK9/Y4ELCNttLUDvBbwZAAAAAFIOFgMAAABAysFiAAAAAEg5PWsGhspG8Zosz+f0F3XxoIIocBMZxXMW6zzH4WQyhYg8kRysN3Te9czUlOpbaAqThpzOV0ZlnperlLUxkPN4/r0rnVSIzEIbHXGYU1Wdczo8eYS1t4o8FRHRrk0V1j51SptoTJ3lRS02bt6qYhp1ndPNZPm9ta6/zB8vzukctx/wk80axaRWg7iHdKWpIRBmJr6RoHZi41IfQERULHItRb2mc3ou1veFhEHW6HBFhayf4EYlhmSBFkXhklZDj8GFOa0JmhamQ5s3rVcxUci31Y10sjqT589cq61jhod4oaSrr7pKxRw/flr1uVi4y3h6ntImPT98karVwjmrOBMfFzKvTkREkRj0hjFPL6gyRebxWIWfRFwPhZIs0yEnDI0mT+g5/sThO1Xf2BDXho1W9IMxdfoka9//4CEVM3mKj7mRAT03bs3xZ76vf1TFNOr6+Wo0eK4/3zeuYnzxXNSr2nSpOse1NK0mTIcAAAAAcB5gMQAAAACkHCwGAAAAgJSDxQAAAACQcnoWEPYVtclP7HPhRC5XUDFSW+KMkk75LP9cpqBFft0OF/nNnNEGJNMzs6qv0ebCNz9rVPITldZKwToV4wtRXccwA4kive1OyPump/QxVqu83VrQgpxN49v5diO9/4cPnWDtsXFdiU4JrohocYGfv2cYe3Qjfh0tUV6nw7dzZmZaB11MCIGTVR1NEhsXRo6d2KicGRqVznIZ/ngODemqZqOjvCJhoaBFm/U6HyvNhhZq3Xf33aqvr8RFWD/ytCermGuuuYy1+3N6/21hOhQaY7cjKjJu27ZNxRQL2jCsVufjMpPT1zYj/uZxxvX3iO+/l3v9eGCNJ3n3rEOV1QZV9UEDSwioPmXMe7JypHVMlhBSfio0KsEGQoB+3z1aLPilf/uq6nv6k3az9p7LNqmY/n4+zz31umtVzOLCGdaWFV6JiBbnZ1i73dZiYGdUnxyqcKF4qWCI9D2+vxLpiWJ+kYu5w875VYvFmwEAAAAg5WAxAAAAAKQcLAYAAACAlNOzZqDT0euGWOSYwlAXg1AxRhGFZkuY1fSNqJjWIv/c4oIulLMwb2y7y/fveUZeXxTv8Y0CHiODXNfQjnSCS+bMiYjqTX5Num19HQdE4ZawpY/x9BQ/35xhbnPffYdZe2L9ZhWzcZPOOzfbPMe0uKBzXrHIVRWKWldQF7qOVnh+uasLTS+GQue9bbFxa7P1Br8OoVHQy3N6POWFGVTfgC5gNTTCx85QRWt7Wg0+LseH9fM1PKALHBWEg9Huyy5TMaMj3IhIamSIiKgtzs3IH7e63LyoMqB1Q0NDg6qv2eRFzgLj+gcBNwzLZFf+G8gZ5kmrQWhoBmSPWUBK9Fm+Wz3VYlJVkVY+HiIy/sw0TIfkd4OhR6CWKJbV1YY611y2Q/UN9XN9yRnDpE0Wgdo8rjUp/ZfxAlpBRo+LUpmP1fn5ORUzc1bvf2CQP4flWlXF5IS53WBOG+JRzJ+dZhOFigAAAABwHmAxAAAAAKQcLAYAAACAlIPFAAAAAJByehYQep4hIBRiobohXOgKkUa9pas3LXa4SEQW3CIiai5yUVu7auzLqMbWEkIgZ1TGajb5tkPD/aKQ5RWlwkgL+Ii0uGNQ6LnKBUOcOFRh7WImq2I6Hd534ow+xmaTV9ia2HCPilm/7tmqL5/n2z515qyKcUL/0zeoBWeBsEPptLWgcjXwfH2vAmkEZMugVkSawrSaegzmi6L6obEE931jXIxUWHuTUTVwSIyd/rI2/Snn+P21jGw2b9CV1goFPp77jGqekRTaOT2lSEGuM0yH5EOfz2qBaimv+4QnDXmWwE0YvoRdK4afhzXfrQaRMV/JY7Niwkiejxbwad2hIUQU19OS3VpmRbG4n5ZYUV7zwJj3MrEQEHa0OC/vdCXDxTneF0Va3N5ucrMe39Pju9LPBYQjoxMqJivGpTUGH25rMXWjxg3omjUt7g5Dvq36ojat8zpcXN4yTI96YW2MeAAAAACsGlgMAAAAACkHiwEAAAAg5WAxAAAAAKScngWE3a4WYHSE0C5jCEBkkbxszqiIJxzZTk1qQcjcFK8MNT+vhYitlhasdYVwJmzr88gIgZUpthGV/PIlLfawXOQy3SrvcFrcMdgnBCehFkeemuFizQeP6IqA+Qzf/0MHTqiYXdu1E9bWHdtYO5fXa8Rmi2+7tqgFMZ0uv/4ZwyVxNZBiQSJSSihfKiRJiwqtcaEwhFK5gD9mYaTH6bBUmhLR9m280tq6MS3yK+a5M2YhqwWEWVFxtLaox1e9pu9nrSaO0+nnOwjE82xco66YJ9otLbKUMZbQN7Iq+ImuXkacdJ5Lts3353trw4EwMsSW8hJbWkdPjOfYCJJCbWt4q0fHEMfFhqOkfOYyGf1VU8jy8TQ0UFExmVA4Uw7qeffIkf2qry1E4b5vCDFj4Zbpa/fM6szDrJ015sZsnjsX1mraJdFUUIrrLQW7RERtIdJvNQx3WOHeGVouoD2ANwMAAABAysFiAAAAAEg5WAwAAAAAKadnzUCzoXOKC3Wet89kDXOXHM9hnjl+SsXc/f07WTv0tK6gKvKcDcMYqN7Ux9gWuZqoo/MpQYdfhsWczo3Wm2OsPW7krjyn83vZDs9V5Y2KaUHMc7N5Q1dBWX7cM22tmSgLOcSxIzq/dMfee1VfZZhX3Rod09XhZmb4ts5O66qRTuTgikZlw9XAMhRSGgErX2roCCSe+GDG049UNuD3PMjpMbD7sm2q78nX7mbt8bEhFVMucc2AVcGuK8yfrOJwZ87MqL4g4M9uZUBrFjqiIqGVP24IjUCtrsdlW1S8tPQZ2YyeX/xg5aqRTggLLJMcX9zHuKeSfo89YWjcLKFnyPjGNC7LN1pjOZKGQoZOQ5hhZQz9TV9e57r7y9yUrFgoqJisGKvmX6Y+H187LtmpQuqLZ1Tf8WMPsvZiVY/vjHgu8yV9BO0On2cXFrTpT0boyarGvsjQLDhxva3vWFnAtlE39D4NfoyxYarVC3gzAAAAAKQcLAYAAACAlIPFAAAAAJBysBgAAAAAUk7PAsLAELV5LS546Fi+CkIAc/ioNsKZOs0FIFc++akqpiqqFjadUUWRtPAvFOKpTEYLWcqiGls2KKqYmRku0vCNqoX+4rzqGy1xVd/YiN52s8ZFIRs3b1QxVzyV923ftU7F/OC73Hxj7qwW+e0/pMU26zYfYu2rhXCNiKhQ4mIyT5aLI6KsuP5mdbpVQArIiIhicfhSQEZE5BliPB0k92XEiMpju3ZsVSFXX62v+ZbN/B4P9JX1tsX+2oapVhzzg3SmMFLfz1KJ7883hGpSZ9ft6nveFs9g0xD6OrF/z9PmSaOjY6rvqBAkW+cmDW88Ka4jIifEdGGkBcqrQaejDap8IXyLPD0XxRG/dxmjcudiW86X+t4N5MX81ae/B0YrA6ovkFU4jWeQYllRVp9rHPF5vzKk9zU6og27WvUK33ZHC+9abS5stcaFfL4t871ul4+VTmiZahmmfTVh2jdzWsU44t8X0/NafFsXQv4wPj+zN7wZAAAAAFIOFgMAAABAysFiAAAAAEg5PWsGwkCHBiVpLKHzSU7kXbdcpnOj1TbPVY1PrFcxzS7PL83M6ByQ57QeYHaKFz0KjdyVC3l+srGgjYk6Ic9nBb7Obw15OudWEkYWQ4M6F7pl6xbW3rRJm7tsWsdzZVdf+hQVM1ri+aXPf+k2FTOr8oREBw/PsfbEujkVs2U7L5pTswyeRLGbUlHfj9Wgp9y/gXOyUJG5dfEZLRoY7Of526uu1M/A+GhF9YUhv56Nuh5fLuLjy8rZ54Thy8QGbSpVKOi86+lTXF8yV9WamK54LutN/VxOneHPYNMoKDaxYTPvMMxtKkPadCkvjK3abf3sdmXhFksOsDY8hhSdjjYX8wOucVrwNqiYyOdzaF9G56xP1fk1HpauZUS0a4jnqEf7DFFMqMdFS2gdMlmtlfIDUSAuNvLxTTkX6RtVGdbz5bwYq9ajW13gOfrQMJqS5lftli5CFAq9iTUHxIaWZbHG72030oZ89Q6/15Ozenw3hTNRJIuH9QjeDAAAAAApB4sBAAAAIOVgMQAAAACkHCwGAAAAgJTTs4CwOq+FLHlRMa1Q1iKkIMtFIpu2apFGocQ/V1/Upg1ZYayxbnhExwTabKE0wLfdaGjThpaoqpYxqqP1DXADmHxOxxRIV6saEALCkq8FIOsq/FyKBV0FLBImKJmM3s7uy7kQce99D6uYyVNa4NWo8XM5fkgLCDeNcEHSlgEtQjvW5Ncxa4jA1iw9CMisECkWyhvanc1bx1l7dEwbp8jqbERanGdZiXhiPd/u6O0s1LkQ0TMMaNpNLd46cZILrOYX9BxQEGO12TKqmwozrmKfnicKfVwcmMlp8amX0dOVrEhpVU2MImFuYzpD8e34hmB6NWg0jfkq4IK5ua4eT7Hjz/nZrha+jQ/wsXPluH5eR/P8mW7XplXM9NlDqq9Y5mN+ZHyHiiHHx2oUaWGpFOzV69pILVvQZlzFMp+foljfz5YQlnY6+lo7IT1st/X8GcaicqfxpIaGAVs34tuen9b36PQ831+tpe+R8/h3rDEF9MRFNFsDAAAA4LEAiwEAAAAg5WAxAAAAAKScnhNj+aI2jZB9ra5OVsjsiZ/VpjdDwzxfOHf2iIqZnTrL2mFd6wpyRp6vv8zzSQNGvlJ9pr9fdwpDo9rclAoZ7tPntmGcJ5H7svq4A1Hgx/cszYA0wNE5qGye56CKRZ27skxp6k1+jMcmtR6hdAfPC+7ZrY2hxoeGWTt0a6NQkVWESOaaTeTHrI+ImJFRbYBS6udjbnZe5z39jL5WxbwYz/167V4u8rHaNAoVzc7xXH9s3JaZ6VnVd/AQLyo2N6fNZfIit1/qM4ymfL7DjmFedPTYMf6RjDbnmp3Vx5jJiOJYhmZDTjmWZMBbo38W1eZ0Hnm2/hBrnzjxPRXTCvnAvHSLLvJ05Y6rWXsoqy9eU2gEZs4eVjEnjh9XfZddyU2kPCOP3m7yOb2+eNaI4WOlaZhaSdMfIqKMEO+0qlUV0xBzYTfUA6OUEds23IsioQcII/0MRpbZHfExPl/Xn1sQxYy61tgVLlqdtqWJWZk1+ggAAAAA4PECiwEAAAAg5WAxAAAAAKQcLAYAAACAlNOzgLDUr01mQqHEqRmGPnlRyTAT6PVHs8GNShYNgVFtrsrbs1UV0461gLHW5scUGEY4pQIXQhb6dEwu4MqRcl4LQrat08LDrVuEYDHUxhoDFV4RsK+sDZXKOS4uyRhCqZao+rVt22YVc+igNkaaXRQVGXMVFXPgFL9HLntCxVy+h59H2TCJWatE8cqiG8usJp/ngrmMIXw7Ncmv+YkTx1TMxISuyLf70p2iR297scbFnpOThjjvKK8+OH1WG8eEoX52ZHVB5+n7GQlFlaGTorxQ8AVZvZ28EHxlDdMh35g72qJ6Zhjpe+Qbx61inDyPtVHGcG5W36tCwEXIrck7VUwr5NfvaS/8ORUzIqb0U8fvUTHNJhe7Fg1x9WVXPF31DQ1P8ONpaCOzhdmTrF2b13OTNCJqNLSA0Pe1cDtbEM+KIfwLfB5Tb+tnp9Phx22JFUMhnPcNQ7qI9DFKU7HQEHc7UdHX+IpT38Plfi1A7wW8GQAAAABSDhYDAAAAQMrBYgAAAABIOT0nda0UWrvD85VZw1AoX+C5q2ZNm2hMnuIFUSijtxOIvJBraIOGwZI2RmqL4hPVus4LZUb4mqhlHGM2x7czWNS5yU0bN6i+sXUV1p4+c0rFFMs8X1zu08Y1nea0aGvtQSbg12j3pdtUzMljOgd5/wFuSlMJtDFTVeTuTlS1PmS3KCZVKOoc92pgGQw5kdy2i9f0sG3h4LNYN4qtdHgutNvVBX8yWZ1n3LKFbzs6q/OuM9NV1t6//6iKOXCI52a7HW0qNbZOm9IMCLOkwMiFxsSvWzvUplp+yMdBwXpOhT7BD/TY2bJZa2Duf2A/a8/NVFWM58lE68p/A3m+kWReBS7doPO/G0a4kdr1u56vYjJFPqcMDunreeLwXtb2s1qnsXHnDaydN/Qe5Olnpy3GeNjR42Jhkes9zpw25sYC31/X0Lb4Of19IcN8T4/dYokXeOoY216Y599NsaEtanf4XJIN9PG0Qj0HtdviOTS+Y+X+wo4OKo3xZ3dwfJ2K6QW8GQAAAABSDhYDAAAAQMrBYgAAAABIOVgMAAAAACmnZwFht6kFe1khKPKyWnTTanOTiKNHtOHK7AKP6RvSpjulYS6SCNwZFTPktDBpvs4Fc35ThVBelCyrzevqWaURvu3Kei3SGN12teob3jzO2sXCERXji6puzUgf5KIUWDl9PzIBF5eMDOjbe921l6q++UVeiazT1mKfSFSoPGNUU5ub56LCkeEBFbMaWEZTTql1elgXm5oy3tloGAOszEVgsdP76hgCo+OTvDJmt6Xv+cxZXsnv+Ek9djshFypZHjyLDS2srYxwAeHgYFnFkKhMGXhWWTcugooNZ6KMMKjK5bXgbbCsha0T67m5zXxVj0vN2hAH9sLlu3aovkhU1/MNBzJpftUxKsrmixXWHh7fpWIKZf7cN43vgU5TC2K7LT6nZ/J67AwM8cqnjaYeg7GoADgyrMdArqAN8Y4e5lVWmy1tVlSrC0MhwxCuv8LF3K2mrjjajfj5d9p6fHdCPeZC0SeFiEREofAhioz72Fnk180f10L2XsCbAQAAACDlYDEAAAAApBwsBgAAAICUg8UAAAAAkHJ6FhCGhjDIF2sJzxAG1Ra5cCM0bJayfVxglSlr162dV+1h7YWpqoqpnzit+vwOF4UMympWRJSNuCgj62uXqZxwuRreooU9gxsvUX0tYXzlSuMqxkVclNJsaZHKzAwXu/SVtMtVLsOvbTGvY3Zt105zi3V+b3+w97iKmT/DXfQqZS0kklW3WtJha5UoFLWwNBQufFGsK4ZJPE+vnX3xXERGWbGmqrSm9zV5SrsLzlX557KBdlGTgsWW4S7oG+NZ0m1r8VSrzve/cWJCxZSFwCwwrlHY1mNFkhOOgxnj75TmghYHZoRzZCmnpzQtWNTX0ZciU0N0uho8sO921ed53CmwMjisYjZuuYK1+4yYkfVcHBfH2lW0NsdFrNNntcivawj/shl+jXNlPS5lUdNCUc/7jkSfcV8ajVnV1+3y56JjDMFAulx6+hlwjp9HbIhPnXA37HQNAWHHcC5sC+fblv5cV1UtNNxUI35t1VjukbUx4gEAAACwamAxAAAAAKQcLAYAAACAlNOzZqBt6AHaIodXKOgcdb3GczeZvDbIGCxxQ4pSvzaRGK7wXHuh2K9ijtx5p+oLjvK4qmGoUxrgObixEV29a8eu7bx9+ZUqpjCizR5qizzXXq3q3FlJVP2anppSMQvVKmsHpA19InH5KwM6V97fr/Oll+3iueC5Ga1ZWJzlfXvE9SAiKokKldWeDGAee6JI5/FjqwynwNIIrLQdw3eLImH6E0d633Gsx2W7LbQsRlVQeRqBUTEtJ5Kz1nYsWsLkqDqrc8NRl49dZ1R1I9EXGdXhwojnfS2jqMjYtif6Nq3TZmC+0FqEkdZstDu8r2vco9WguTip+nJ5Pj9mg/UqhoR2pW3k9UNhBtXtaGOeY0cOsnZtTmtbFub0fFUe4PNTaUDP6Z02/24Iu3puLJb4/O2b1ST1vfKEHqA8qCvBLiyIfDzpa9Ro8HkvMoZ3q8uPqd7UQUaRWao1+P7bLUOPIIyJHOltDw3zMb9tx1P0znoAbwYAAACAlIPFAAAAAJBysBgAAAAAUg4WAwAAAEDK6VlA2LEqfQlhUqerhTnSmGh4oKJi+kRfaFR1qzX5tgsjWpCy9YYnq75Ln/l01p43BIS+x4VSpZwWaWwY48fYV9LVsxqGcUtVVPdrNQxzG1G1cHa2qkLyOS68LBa0QYfvcdGQH2gBIRl95Qo/3127N6sYr8Wv2+bxiopZrHEhUWiYb6wGssobEZETZjW9iAV7wdqOJXzTx2OYifQgcszlhFmPb5hqCTFe3hDxyuth7b/Z1BUZZUxkiMAyYv+RIeBrifEVGAZL8hkgIspl+fn6vv5cQVyjRlPPAYHP54DYrY3Khrsv1cK3dps/+/WaFuoeenAva/sZPZZ8cV2CQAunDx86wdr9hjHQwmJV9c3XuHC6tKirFnZFlb5MVt/fBWF8ZYlPy336uyBf4MLD8qCuhDtd5fNVy6gI2BZzer2hx3e9IZ4To2phq6PHU73B++KufgalMZPnGaZ9wuBpbGyLiukFvBkAAAAAUg4WAwAAAEDKwWIAAAAASDm9awYMEw5ZXMQ3zB8GKjwP5BlFWgoZboLSMoo65EXyJMjqdUyhTxsR9Ze4+cVQXufFclm+v6Kvc0eB4/nSZqOmYlpNXQ2jNs+NLPqNfG3G8bxUJqNNYcolftzlPsN0KOS5UCtPVejXBUv8LP9cJqfzrpKgqIdOVJMFOwynjVXAyof3gixCZBkV9VQURHzOz+jPZGVykIhyYqxYuX61f6NQUiTO37oeVq691RJj3tAMSAOfjFHQLBZ9vWghGg1dNMfSGsi+IKPPIyfnCmcYM2XF2LXcZVYBz5hTXcznnocfPqJips5yE6es8UwXy1z3lC/ouVEMAVo8q/UWzY426/HFNV+oz6iYToePVWd8HXnCRKvT0WOwUNA6qPExrnuyTKw8YfTlO/3seKKAmW9IvopiOBVyel+WbGhkQMwvsb5HTmj1ImNcZotV1u4uHtI76wG8GQAAAABSDhYDAAAAQMrBYgAAAABIOVgMAAAAACmnZwGhZ5hwLIiKhHWpNiGioaEKa1f6tfnEgjB2sIxbyv1cJJLR3irmMUZCpBKFuupWWQizuk1dvaslzFQWFg2Bk1WaShgx+dqzQ1XrWr9BVyErlfgHc2W9Iandmpw8o2IWWtOqryyqTeY8LWSZ7wohT1aboeQHubhlZua4ilkNehGskVENTGpmre1khPAsjg2Rm+gLPEPAZogDR0f4NS6X9bPTEqK+tjF2A/E4ZbP64QkMAWMv160jTLw6hlJKmg5ljP1LIWTGOJ5GQ59bu8NFu8W8vrZFMZwtOyHl5WKIFVcDZ8xpvjBIKhb1vJvL8r6ccV2kGVXG0+JAeV2qs3pOacfaiMcTplGR09dzfp7PoS7W59ov5v0+eTOJqOwbgnPix5k1vlM2DfMx1u0fUjGRME4LDYGufE6cIZK3jMec2JZzhnBb3X/j73dhJBd379AxPYA3AwAAAEDKwWIAAAAASDlYDAAAAAApp2fNgFXs5fQUz8sUjDx2ThS28IxcYCDTIkaustPh+fhczsiBGWY9nvCjiLpGkRJh7NGKdA4sDHmezjNyQMW8zoV6GX7+MemiIqUiN/8YGNRFkGQhl3pTXyNpwNLu6rVe2NX7j9r8BrQM7UNpgBf6yPZp86JOk+sxWi1twrQa2LlvkefroTBNYJgFSZ2G9ZzofVl5R/05WZTE8POhfIGPuYEBrSsoFrgeITSKvUShznOWivzhabcMwxnRZ227K54Vy+BInr1lsCTnAAvrVrc7/Hm2jKLk/iPjHq0GYaRvuic0J9u3aY3Rpo1cb+IZ15xI5PUj/byemOQGR6cn9QWer+r7Uizzeb6vrOfmkS18Thka0N8f/X28zzL08Q09gDQMs2aASDwXcWg8YGJOjY3nNIqkZkATG0oVOVbDUH+yG/KxG8WGCZXYYxRrg6dewJsBAAAAIOVgMQAAAACkHCwGAAAAgJSDxQAAAACQcjzXmyMLAAAAAJ6g4M0AAAAAkHKwGAAAAABSDhYDAAAAQMrBYgAAAABIOVgMAAAAACkHiwEAAAAg5WAxAAAAAKQcLAYAAACAlIPFAAAAAJBysBgAAAAAUg4WAwAAAEDKwWIAAAAASDlYDAAAAAApB4sBAAAAIOVgMQAAAACkHCwGAAAAgJSDxQAAAACQcrAYAAAAAFIOFgMAAABAysFiAAAAAEg5WAwAAAAAKQeLAQAAACDlYDEAAAAApBwsBgAAAICUg8UAAAAAkHKwGAAAAABSDhYDAAAAQMrBYgAAAABIOVgMAAAAACkHiwEAAAAg5WAxAAAAAKQcLAYAAACAlIPFAAAAAJBysBgAAAAAUg4WA4/k3/+dyPOSfy/x+tcTbdu2Oscj8Tyit7515biPfjSJPXLksT4icIFY60OPiOhd70qO8WLZLlijXAyD/bHkOc8huvLK1T4KBRYDjxV/8AdEn/vcah8FSCEYeiA1/LCD/f/8H6L3v/+xOpqLGiwGVuJv/5bowQd/+M+t5oz8Mz9D1GwSbd26OvsHF4S1NvR+53eSYQXABefxGuxYDDwqmdU+gAtCHBN1OkSFwoXfdjZ74bf5WBMEyT/gMSdNQy+TSf45F4/l9QCrTJoGOxFRq0WUyxH56fibeW2d5VLycP9+ole/mmhggGhkhOgd70huzBJLufO//3uiK64gyueJvvSl5P+dPEn08z9PtG5d0n/FFUQf/rDe14kTRC9/OVG5TDQ+TvSrv0rUbus4K5cVx0R/9mdEV12VPBhjY0Q330x0++3Lx1evE/3d3yX/7XnJdpbYv5/o2DG+zQMHiF7xCqL165NtbtpE9JrXEM3P62P63OeSnNPS+S2d+xKWZmDbNqKXvIToK18huvbaZB979hD94z/q7aeQNA+9b36T6FWvItqyJTnuzZuTY5JvAazc/qNdjyNHkv/3x39M9Kd/mrykKhaJbryR6L77jBsg+MhHiG66Kbk++XwyVP/qr3Tc0rD+1reIbrghuSY7dhB97GM6tlol+pVfSc4vnyfatYvoj/4ouaapIq2D/TnPIfrXfyU6enQ5fmmfSzqGf/iH5BXYxo1EpRLRwsKji1oeTZv1b/+WDPT+/uTaPuUpyRuJc/GVryT7+6mfIgrDc8c+RqzNNwOvfnVyk97zHqLvfY/oAx8gmpvjT/jXv0706U8ng3V0NImfmiJ62tOWB/HYWHJj3vCG5Kb+yq8kn202iZ73vGSgvP3tRBs2EH3848k2e+ENb0gGwoteRPTGNyY375vfTI71+uuTbb3xjcns9Au/kHxm587lz19+eTJYlgQ0nQ7RC1+YPCRve1uyIDh5kugLX0hmsMHB5c9+61vJF/gv/3Iy2D7wgWQRcexY8kCfiwMHiH7yJ4l+8ReJXve6ZMZ91auSB/wFL+jt3J/gpG3oERF95jNEjQbRL/1SMoRuu43ogx9M5vHPfGblY7KuxxIf+xjR4iLRW96SfM/82Z8lX/L33pt8jzwaf/VXyffLy16WvI34l39JhnwcJ9t6JAcPEr3ylcm1ed3rku+k17+e6Lrrkm0QJed3443JY/XmNycLn+98h+i3fovo1KmUvjlO22D/7d9O/rg6cSJZoRIR9fXxfb773cnbgF//9WQ+zuV+qEtKH/1oski64opkcFUqRHfemcyxr32t/ZkvfCEZwD/5k8ngXa23um4t8c53Okfk3Mtexvt/+ZeT/rvvTtpEzvm+c/v28bg3vMG5iQnnpqd5/2te49zgoHONRtJ+//uTbXz608sx9bpzu3Yl/bfeutz/utc5t3XrcvvrX09i3v52ffxxvPzf5XLyWQsi5268cbl9551J32c+Y8c/8nO5nHMHDy733X130v/BDy73feQjSd/hw8t9W7cmfbfcstw3P59cryc96dz7TQFpHXrOLR/bI3nPe5zzPOeOHl3uW7pGcnvW9Th8OPl/xaJzJ04s93//+0n/r/7qubdrHdMLX+jcjh28b2lYf+Mby31nzjiXzzv3a7+23PfudyfX5aGH+Od/8zedCwLnjh3T+3vCkubB/mM/xvezxK23JvE7dujBZw1Q5/Q8W60619/v3FOf6lyz+ejHfOONzl1xRfLft9ziXDbr3Jve5FwU2efxOLG20gRLyKX/296W/PuLX1zuu/HG5N3hEs4R3XIL0Utfmvz39PTyPy98YbIivOOO5e1MTCSrsSVKpeXV5bm45ZZkRfzOd+r/1+vvo5zjf5ot/eX/5S8nf8Kci+c/n69+r746eRX18MMr73fDBqIf//Hl9sAA0c/+bLJyPX26t2N/gpO2oUeUvL5fol5PjvvpT09i77xz5W3K6/FIXv7y5I3rEjfcQPTUp/LrafHIY5qfT47pxhuTYS4zZ3v2ED3rWcvtsTGiyy7jj8RnPpPEDA3x+/P85xNFEdE3vrHyeT7hSONgX4nXvY4Pvh+Gr341eQ32m7+pdRXWMX/yk8nbgDe/mehv/mbVtQlrM01wySW8vXNncqEemZvZvp3HnD2bvFL/0IeSfyzOnEn+ffRokjCUN+iyy1Y+tkOHki/V4eGVY3tl+3ai//bfiN73viQ/96xnJe9Hf/qneYqAKHm/KRkaSl7vrYR1zpdemvz7yJEkPZFy0jb0iJK3uL/7u0Sf/7weRpZkRSKvxyOR15MoGXKf/vS5t/ntbyffA9/9rl4fz8/zx6KXR+LAAaJ77kkWChZL9ydVpHGwr8S5BvNKHDqU/LsXD4HDh5P5/VWvSnJya4C1uRiQWKsquXpbUgH99E8nqzuLq6++sMd1IfmTP0kSnf/8z4mY5O1vX87lbdq0HPdo+STnHpfDTBtP9KEXRYlcZHaW6H/8D6LduxOt18mTyXDsRVx3vn9IPRqHDiWp5t27k/Xx5s1J6vaLX0xSvfKYenkk4jg5z//+3+3YpTVxqnmiD/ZesAbzo72JiKLz38/ERPLPF7+YCCKvv/78t3WBWJuLgQMH+Art4MFkEJ7LoWpsLBHURVHy7u9cbN2aSJqd4ze6l9+57tyZvM6fnT33qvV8LNWuuir553d+J1E3PeMZRH/910S///s//LYsDh7U5/zQQ8m/0+L+tQJpG3r33psMgb/7uyRjtMRXv9r7Ns7FgQO676GHzn09/+VfEu3W5z/P/+q/9dbzP46dO4lqtZXvT6pI22A/n3ii5DUTUfJGpFJZ7j96lMctpW/vuy95I3IuCoVEOHjTTckvJP7jP5bVrqvE2tQM/MVf8PbSa5QXvejRPxMEiar+llvs3y6dPbv83y9+MdHkJNFnP7vc12g8+muvR/KKVySD+/d+T/+/R/4pUi4ng8dC/uRlYUH/nOSqq5JXdtbPcM6XyUmif/onvt+PfSz5qSFSBESUvqG39Ff1Iz/vXKL6vxB87nPJW4YlbruN6PvfX/l6ymOan09+/HK+vPrVScrhy1/W/69aXbVfc60uaRvsS/G95L4eydKX/COFJUs/aXwkP/qjyULpPe/hP9GUx7zE4GAyIMfHk9dWS2mGVWJtvhk4fDjJmd98c/IEf+ITyc8yrrnm3J/7wz9M/nx46lOJ3vSmRPgyO5sIWr72teS/iZL/9+d/nvwptHdv8rrm4x9PxC0r8dznJg5/H/hAsrK++eZkNf3Nbyb/b6l2wHXXJft83/uS3Nf27clxEemfvHz968nnXvWq5H1lGCbHs/TgXSguvTT5uc4PfpD8ruvDH05+JvSfmWWfYKRt6O3encx1v/7ryZf2wEAyz/ciQemFXbuInvnM5GeL7XbyE76RkUd/XU+UzKm5XKJRe/Obk7/o//Zvkznz1KnzO47f+I3kTcNLXrL8s8N6PXkz8tnPJmny0dHz2/ZFS9oG+1L8pz6VaLSe8pTkp4Uvfem5j+VHfzR5RfWGNyQDKQiSuXNsjC82BgaSPNYb35hs+7WvTd4q3H13sgiSiweiZNB99avJQ/L85yc/HX+k4vbxZFV/yyBZ+gnH/fc798pXJj/TGBpy7q1v5T/VIHLuLW+xtzE1lfy/zZuTn2ysX+/c857n3Ic+xOOOHk1+WlMqOTc66tw73uHcl7608k9enHMuDJ1773ud2707+anf2JhzL3qRc3v3Lsfs3+/cs5+d/LaKiP/8Rf7k5eGHnfv5n3du507nCgXnhoede+5znfva1/h+H+28t27l23+0nxb+2I859+UvO3f11clvr3bvXvnnjCkhrUPPueScn/985/r6kuN505uWf7H6kY/oa/RIHu16LP208L3vde5P/iS5Jvm8c8961vIv18613c9/PhmmhYJz27Y590d/5NyHP/zow1py4436PBcXnfut30p+2ZbLJef69Kc798d/7Fyno7fxhCXNg71Wc+61r3WuUkn+/9I+l35a+Gjz4d69yU8Gcznntmxx7n3vs+dZ55LB+/SnJ8c0MODcDTc498lPLv//R/60cImDB5Ofa15+uXNnz9rH8BjjObeGlGfvelfyWujs2RQu0x9jtm1LVK5f+MJqH8maBEPvwnLkSPJH2nvfm7x1AGsIDHZgsDY1AwAAAAB43MBiAAAAAEg5WAwAAAAAKWdtaQYAAAAA8LiDNwMAAABAysFiAAAAAEg5PZsOveV3/6fq63Q6rD0zM6NiyqJe9OCQYS3pcXPxmWnteDIyzCuMbNq0WcUsLBr7L/FCP9u2XKVinONm56emHlIxp05Psnaz0VExUaRtzLphl8cYXu/zSyYd/z/5jLbMzIoqWMWS9tBuin01ajW9s1hnhWJh9l4y/LmLRW4U4khvJ1vIs3YuX1Axf/4/f1Mf02NM8LSX6E6ZHTsPl1KQLqLv/evjvs8PfuJTqu/mp97A2s2FporJi2fvyPSsivl/P/fPrL3otNtpURoExfrvx0pRP+ev/dGbWXtjoV/F7BOOe9P1RRXTDPhz+sAR7dL3nbt+oPqOn+TOg56nj7vb4ec7UBhQMX7M5/SxET03btk4xNq7dmg310yg6xjIedcZf5vnslnW9jr6OyYjJ69Qf8m8+7f/XPVJ8GYAAAAASDlYDAAAAAApB4sBAAAAIOVgMQAAAACknJ4FhDM1Lc5TFgV5FUKNsM7a7aoW3rXavC82RHbxAu9sn9Bil0ZLl6bMZ3OsPb2gY2SJ69nqCRXTFTVOo65WnHW7Wtzh+1wc2enq425GXDjTNdZoGSHW7AT6Oi40uGCwZgkIDXGJFLIUO1okk21wIUuQCVRMVOUimdgQK64KppWGO2cTnB+mbcljaWUiHl7vfOrVr2G6oRaeLSzw+SKI9TQeCaWydV+CDP/c4pye45tNPocM92uRXZ6yqq8jxICdQMd0Yz6HtUMthLzj7ntY+66HHlAxtail+kr9XPjYaupth8Tn68DTc/PmMS5A37xR13LYvnUd33dOz9+B098NseP31jMmof4cF2dWBrRYMxDiyOA81dB4MwAAAACkHCwGAAAAgJSDxQAAAACQcnrWDJw8M6n6CnkuEogind9qNBqsHTuds253uVlOPqfzIkWRD68uaGOiTqhz5AVhhDM5NaViZM6cfJ07yor8WhjqdVRfaUj1jYxxk6WpMydVTKYk8p5Gfi/O8JxTnNXX2hOajbyXUzFRp6v6Mhn+wXxeiz9kLtY3crMZn18TK9+5KlgpNGgEHjcey0v9xFIIaHxPT9Ge6PNI63ec0OtIfQCRnq8j43ktFniuv91Y0NsJ9LZl3rre1nl9L8tj+gfKKmbbFm4uNzBcUTGWAVokNF71ZkPFNMV3UyHQ303rhrlp3voxPceXi/z82w1tnpQ15nQv5tc7Z3wbDw9ws6Z+Y24OAn7/w1DrE3oBbwYAAACAlIPFAAAAAJBysBgAAAAAUg4WAwAAAEDK6VlA2Fisq752g4tCMoZIpdHgZg8xaZGGFqfpNUptkQtXGp4WhPiGAKQrzHqc02IbKSAMAqMiX45/Lo71doYHdbUqKe45e0YLGDtdfm27hjGQF/BrUh7QVcBieR393pRzHVHtsFQuqRhfiFTIabFRIASEJaOyIrh4MQ2FZIzR5zk5L2iBrvPkJ62pyRKkyjHey983F8/fQGFXn3M+x58r19ZXvd3m864znNxk1dlsVhsDDVYqrF0/O61iSkUt/Cv1cbMeL6O3vWv35eIzejvPKHARtCfnISLKhsaoE+JIWZmWSM/7IVmVaIXwMdIC7E6bfxctzldVzNysvm7NBV5JMkt624GYZ+ttfYwFMV+frmpxfS9cPE8FAAAAAB4TsBgAAAAAUg4WAwAAAEDK6VkzMD+tzSakOU2xoM2CShneV2tp7YEX8LzfhrEJFbOwwA2FukYura9P59HLJZ5P6Tdy7RlhmlGr62MMQ54XarW0iUbGqNTk2vzcwqbOC7WEIYdxaqogi4v1Oi5X1NdfEhvFlELR50daa1Ao8DxlFOrcVbfDr1shv/LxgIsbpSNQuX9ShYrMENnpGQ+Bp/O+ThUqso5SdF5EhlOBUeBHXnJZlIiI1IWQxjRE2pzGMqupCc3XyDqti7rpeS9UfZkiL2i00NAarz0TG1jb8/Wc1pXGSLEeF6Ghh3CxHAiG1iAnzNZyhlZK6K6yhg4rJ6+t3hU1WtoQb+rEw6x96uhBFVOf58WjZtt6Oxlxr+eN69gLeDMAAAAApBwsBgAAAICUg8UAAAAAkHKwGAAAAABSTs8CwmKgDWTCFhecdA1DhnwfF2l4HS3ACLJ8TVIMtPDM5fnnOoZBQ1jT4pKpWS7AmM9rIaQ025idnVcxUczFcc4w3fHXD6i+8npe9SpuG2KXLu8rZvW19oKVK5XFHb6dTldfo5yvb3nW4+cfdwxjoogbxSwu6uvYFiKZTIC1ZuowngtyYhy2tbkMdYUgtdTUMRldhZOcENb2oA68mCodFkta1JYT5e0aLW3ilPNFJbuGFgdG8toZl64lhNt7rr5OxYyOrlN9t37926zd9fR81RBzWNcUN0ciRs9p1vdOFAlxZKS37QnRasaYGwNxjNmMPo+BPj7H9w3oe1bq12N3oca3NbWo58tmi8csGPN+XjwXVcOQrxcwWwMAAAApB4sBAAAAIOVgMQAAAACknJ41A1YuMJuRawmdD5+f50UTOoaxhefzHEuzoQ19Thw7ztqRYTRhmW+EoghPbBSskGYbsbGdTI6fazajDYbCSBvxEPFtu1gn5uQhNVo6X5oRuoasUShJmnbExrXOlrWJSSBy+y40inF0eV7S8NXQRh++FQWe0CizFyInnqeg1adiSOa9c/oZiI1CZPLvmV6KKdnGRGsUw+TGE+ZLXsbQIQndT9Q15kvRFXb0fLGuxHVQW4a06dCD+w+ovv/4zndYOyhqs7fJBv9OWW8YGlHIYxbmtZ7LMwyqCkX+1ZYv6HmvXObarG5Dj53jx06wdmyYHknNWTavv1bL/fr7ornAvxtrc2dVzNat46x9tqVjvEgU8etAMwAAAACA8wCLAQAAACDlYDEAAAAApBwsBgAAAICU07OA0DLZiYUYrtnUop+uEKN5RhWuvn4uUrFEQNI0wqosWCppkUZJCOY8w3Kk3pAVCbUQMIr4uqlrCHK6oTb/kMI7yxTFF4ZCcUdvp9nkx+SMCpGeUEZFkb5nrZYWl2QyfP+5nDbIcELlGBvjQZ5bq2MJKtOHvufnWzbPEJNdIAudHnR3j3LUotfS+AlzG2ppMRl1hGjVqFB4cdkFXRhyOT1fZsXzWbDMgkIuwi6WtNGTE/NDs6bn7w27r+Cfyeh555577lN9p2e5OG5wRH/VHDr0EN9/Q1fky3l83p0X2yUiCgJ9Abbv2MLaQwNDKiYU8/XstBbnnZ3iAkJrCMqqt0Fefw9N5Dapvtjjnzt5Rp/b5u1bWbtR1+LudsSvWzuGgBAAAAAA5wEWAwAAAEDKwWIAAAAASDk9awbabW0E5AtTmYKRx86EIh9urD+kaUPcQwLT9/V2wlDnsaXpkMyrW1g5c2no49zKpj9ERG1RgKVjFOMIMvKY9PnLvL5sE2mNQBDoYwwNHYEVdz4URK7MMnhKJ0609BgwUcNCjy/vh/ANOxf2Iyc6rTy+E+cS67yzH47wjpZRqCj3MN+Mb+1r5UN8ov15k/H0CRUL3LRpsaFzzYuywI+x7aKYd/tzusDOFVc8ibXz/boY29ETk6rPiXnW9/XNKwR87PTndcxYZZC1N4/q/XvGto+fOMLa9975XRXTFuY87ba+SsUivyaDA3r/o6PcGEhqAYiIYqPAkjS7a7a1xurkqTOs3T8womK8lti2aX63Mk+wRwcAAAAAPyxYDAAAAAApB4sBAAAAIOVgMQAAAACknJ7VR54hZCkLcUX/oBZX1BYXWTs01h9KDGiomaSo0BK9xbEWZskqU5YRj9xWqVhUMdLoIzKqs5nCQ6ECy2YMsZ7oyhmmFfIaWeeRE4IgS2QoRStEWlQZGxUhZZ9vVFOTMRlV1TIF9CLEO+9tGRUve9h2L6JZ8oztCAGoZ1Rsc/KZi7TQOGju4iGGmMovV/l2Pf0MSlFaclC664mErPhIRFSt8ip10zMLKmby7Cxrz9V1TNTh92pieFzFrB+fYO1T01MqZqGmKwkOV7jIcfPEqIrZtIlv+/JLL1Ux/eI7pt00jN0Mk7aH9u1l7cAYl3t2bWPtSqWiYtav55UUx0a1gK8iRI7trh6Up6e1odJRURFxdGhQxcQhv//9pWEV02xzs6R87vxExSmcrQEAAADwSLAYAAAAAFIOFgMAAABAysFiAAAAAEg5PSsNLMFeVlTU6rS1kKMrqg16gRbZSTGcVbUwkCLDrK7m5QyHNikqtM5DOudZgquWcGB0xqXrGA5ScYnvv2OIp0riOmby+txa4trmDbGidIDM57QQsdnSDnHy+pviRLGtsKvPtd7klST7+wynuSc4tusiH8+W5s2qCqoiDRFvLwLC3rCOmx+TJSAk4fAZdCoqJNMZ41t1d+vtCMdB1+PfKSt7d17cFPLa1fWsEAdOzy2qmIUOv5733P+Aipmfnmbtm258iopxIb+ihx8+oGJOnzyq+lpCVLhwRsc8dA+fQ7/9FT2nOlEZN+xY7p36rjea3F1wfFwL72ZO8fbRA/tVzN1CKF4o6jlVCr5LRT3vBVktiG13xXEb3x/U5Z/LGsJaqf2dPnNab6cH8GYAAAAASDlYDAAAAAApB4sBAAAAIOX0rBmwDGy6HZ7jaHWMnLkwoimWdM5Fbtuq/tcL0nQngWsEuobpTl7kfCzTn3qd58ODQMcUCrpPnoulR4hELjbuGuYuQkdhVW2U17rZ1voAa//y/LuGrkEmZ3PGuQ4H3DTDSHFfZMhqgyuG2B44sfyksaWuNuwij98/P6PvixMV0pxxAE7qGCyDIVMzICsSGlXdxHgqZq5RMfM8fUtxdNLYlXh2I+sYjedCXkvL6EpcE0uTtFYJjBFVGRxi7aOnZ1XMgwceYu0H9mvNwA3X38DaT3vaM1XMgcO8muTe7/2Hijny4F2qryC0WS1DS9MU925uVldfpKY2C1IExteY0Krtuf5aFXLdk/aw9if+/lMqZvKhg6LHGF/KgM14CLNa45UrcmOmrKE1KJT4vHDF1VeomK1XVli7VqurmF646KdrAAAAAPznwGIAAAAASDlYDAAAAAApB4sBAAAAIOX0LCC0RDedkAt6rGp/0mTHqoiXz3NxRcYwBpI6oXq9oUIs3aGsrle2jlEYWWQyWuxRFNWzpmeqKmb9uD43KWrMGduOI36NQsPcpVzm+zcr0Ylr1DLEN9a2SwV9TSSRuEaFvpKKkT5E7VYP4p81TOyJ+2kJz6SA0KhmKTdDob4H3vwletOZw6wd9E+qmEiaeAV6DDpP7M8yRgqN8dThQqS4rs1tNkxcxtpZf5eK6SxwweD2y7epmLn2EdaeaWuxYr7Qr/q8LJ/CFg3RbOikENQQyK5RKgP6OSuK53X7+iEVMzTIhWaX79ioYrKDG1j7wOmqijl5it+7lzxpTMU8e+vTVd/cKS6Ou6lfm/48UOJj7p+ntLD06Ld49cEtY3oMbLhsi+qLRbXHvGHkduYMdx268porVczuPbySomdVSDzIn9OO0/u6/FK97fXC0Gnq6HEVc/9JLmDM3qcNhQ5HO1m7ZFyPXsCbAQAAACDlYDEAAAAApBwsBgAAAICU07NmIDRMQIKA983MTauYbJbn//v7Kypmfo6bZmxYt0HFrBvjfcVcTcVYZkVewPuyWX3KnjCJkAWYiIiGBrmhzlhF544m1uvjHhyssHZw5ZNVTKnIi5H0G+YTg2L/snAREdHcHDft6IbaBKod6pyqNKWxLFkawnRpsa6NLToB1xUMDupc5kVFLMaT6VUjDX10Pj4WRle7t6xTMf/tNT+h+r7yjX9h7c/e+pCKoZLQDHSMfLgUcxiagYG81o2sG+V53h1X7VExu7fx3PRAnzZPGq7w7Vx99QtVzAOHed71nod0YZvpqh5zD5/iOdQHjxu6CvF8O9N0aW0yE1d13yH+nMcdrZ/KCy1J/0BFxRyY5NfuxJQ2Lxro8Dn9NS+4TsW0FrVZ0He/dpa1n18eVTGZLn8uHt45omKGGvw8nnujNrV6+X+5WfX1iwJP3VA/F12xf2cY62WE5qw2P69iPvOP/8ba+6e1tmbPmP5ueLHQaMwberIv9vHxfOM2fYyfWphi7Ya/XcX0At4MAAAAACkHiwEAAAAg5WAxAAAAAKQcLAYAAACAlNOzgFBVMCOigqh21+kaIsMMFyuFhpCjmOeio4G+QRUzNMDNLjodbdxSKGkRVCArIhpmPVlhDGRVBJRGSAN9fSomlzMqU4m+K6/QVafyoqJVt62Ffx1RETJWlfCI1o1NsHYmp82bnK+vW7vNzYHkvoiIWsJAqNbQoqVIbHuxMaNi1grSRMsy1fJknyG8cx1+XVxXCzSpxq9V30YtsnvlSy5XfTc+gwsN73lor4p5+AQ3apkY00Kt7RPchOSSrZtVzI4t46pv4wR/5vrK2gAnFsYpM6e1Kcq++/ex9q3f1CKsY7N8zJ1a1GLBxVhf244weQo9/QzK8pmeYbyl1KFrRGP4rXu/rfqiBh+Hm8fWq5iBHB8H/RVt+nPk6CHWvu3731ExVwzz6+me82IV0zSK5C3O8Wf/eFvPu2GGPwdjxpza2ryJtXOj2vTIEioPC5M4S1weiDk9tp5vMQcslvR309YdfE4/W9DPwPxRLYid//59rO3PaoHw9g187rhsUM8d29r8GA+0z8/sDW8GAAAAgJSDxQAAAACQcrAYAAAAAFJOz5oBz0iiyZxqpV/nMzpSIxDrXeaz3GQnlymoGFkoqOHrnLU0iCAiisT+rVRgLGKs/JIThS/qi9pYYmhI564qlQprT01NqZhYXMdurPUZSjMQGeY2YjtW4Sby9ecikUM18+dCa+Hn9H3MCX3GmTMLxgGsDdQ5GgW0nNTJtPWYW9/Px+Wlm7eqmA1iDAyX9Pi+4+7bVN/EOq4B+eVXvEzFnJjipiQ7t+v9j1b4uCwa2hZn5NGbTZ6jP3Ncj90jx46w9h133qVi7tz/MGvPxEZevywK0BS0PoFkUSYi0n/PGAWXhDGUZ2o/hE7GKpa2CjTmz6g+T1y/wbJRHEoM1YNHjqmY237ANQIHHviBihnaw7f9+Xt17ntxXs+FpzpCKxZVVczpIr/mJ2taExIJzdntP9C6mZOHHlB9/UI/ZhXR88U9tubLOOJzQDfW4+L0Iv9g3ShmdN+D+tqG8/x5GjTG5akFrsvb5rR50Zk2N4tqLBq6pR7AmwEAAAAg5WAxAAAAAKQcLAYAAACAlIPFAAAAAJByehYQBk4LejotLsLKZg0BnxCStAyHCj/ipj/Nho4pi8p+lnFIJsirvs3CtEKKRoiIZqZ5Za56XQvFsgW+bcv0x6ItqgtWq1UV05XnkjWqLwpxZBzp85fCR98SU/VgrGER+HyoGFpNymd45/rRNVK10Dhn3/HrZ97PFq+M+cw9O1TI617+Y6y9YZ0+Z3mv4q4+nuqMrhhXneZ9O7dq8dAlO7mBUKerx658nqbPaDOomZmzqm9+lu//xIlTKubeB/ez9sOndEyzIMxkpFiQiMgXz6VRcZOMyqkSS/ybFX0ZYzvNaW6EFAxXVtzX48Fzb3ia6pua5sLc+dO6auDBQ3xOmzd8lmp1fs6lsq7WOikqEv7r/VqIWC5VVJ8TItV9J/Xnqh6fGxtH9H2JmjzGLerx3ehqAaOf5/NVsaBFu74Yc5HThnhRh4vxIq3tpsIwF+2W83pfnVAf4x3bK6w9mtGGYWHA78k/L+jn4kjA99eYh+kQAAAAAM4DLAYAAACAlIPFAAAAAJBysBgAAAAAUk7PAsLqTFX1BRm5ltDqCs8T7nqGMMj3+OdcpEUivseFWVZlP1mhkIhodIRX65qYmFAx9957D2vPzU6rmMDnIqh8waiQaIgTpXPfhgktAisKF7v5pnbuOyWEWY60CE1q+pyzHBkNBYwQEFqVHfNCEFTIarHRQJGPh4mx7Xpfq4BVjSwjRJuxIWy9fP0Ia//cf9EV2zYOcdfNVkOLdxrC3a5Vq6kYq1KkPO5soMd3t83PY3pWVwScmuUudnM1Pb7jtlaY1Wa56Omhgw+rmAUhkO0f1tXxBkv8GhUHdcyQqDxXLmq3wULB6BPOchljDgjFc3DgoBY5HlgU98QY36tBxahCOS3u1b3fukvFVE/zOaRpKH5bbT7m+4d0RT5fOJbe9m1d2dDFWrgdL3BBaqulXfHikPd5hqtqKL5ispE+j9gynRRi9tFRXZVTjp16TT8783P82QkMIWZ4iLuAOuNr1Qus70Z+vmW/rGKK47wi5V1OfzcGwtF0eKN+vnoBbwYAAACAlIPFAAAAAJBysBgAAAAAUk7PmoHBijaEKBV5Xi2b1bmjYWHesX5iTMX09/Nc1dbN21SMi3lepJTTJkiRYZ5z5OEDrH3y+GEVMzvLjTW6HZ3fajV5LtjP6HMdG9PnVirx41xvaBayBa41mD+mTUSirq6EJXFibRcYOeZiThtiZEV+NJfT+dJQ5POsmm55oZnIZYwE22pgaAaiLs/RD2Z0zGtffBNrr6/onF5TVDKcXdBj5/gJnlOcNwx+mkZONQr59fOMix7J+xLoyqHj67nx1lXXXq9iJsZGVF/U4XnOuqHTqYtnrl7XeohB8QxEhmHWseMnWft0VZu0zNS1HqNa53nv2Xl9bReFjmOmqvUhJLQf0RqpWugZ84z0xzpZ1edcEVX7jh4+pGLGRvg5X7JDV7wMF3ge/aFDJ1RMM9TzblbMzzmn9R7ZLp8v657Oq7dzPPefCY2vrFCPJ/k0ZzN6/9KUrZjXmolgkM+FXqyNiZzj826X9BzbMM7N8/izkjF8tpq1Kmv7eT1PrR9ax9rlkp6negFvBgAAAICUg8UAAAAAkHKwGAAAAABSDhYDAAAAQMrpWUD4X3/6Baovm+Uim2xOry2KwhAhExhmHkJc0mxoQcjcDDfRyGV0dTjL9CcQx2T46dDwCP9cZUhve1FUy/KNCon9fboaWywEXocPaeOWVpeLx2LSSpKRwQprWyIseXKFnHGMpT7V1xBV7Tyj2mFBmA7FkRbSdISJiecZipjVwNMCJxfy43/mdVeqmGuuuJy16y0tajtzlosDHz54RMdMcUFoZFQtJDKOUQgfGy39uI5vuI61f/yVz1Ax/WW+7U3rNquY2XltuPJP//Q51r73wYdUzOkavyYTg/oZuGH3paz9jGc/W8X86+e/wtqf/7/fUjFkGMeQmINIGaGR+pPHMtVyGbEdy8hmFchI1x0iGhSiwr6SIRQW51Ov66qYQ2X+TE9PaiHilBC/npnRhlWZUI/nHY4/+zsKei56QMx7NeOroUtC3GxUnDQeb3Iev26WqZes1upbsuiACzFjX5+H2k6s70efMSxHfH5uA54WOZ72eV+YMypuzvNncGSDFrL3At4MAAAAACkHiwEAAAAg5WAxAAAAAKScnjUDI6M6FyiTNUGg1xYZkbvyjaoS3S7P3+YK+rAyQntAgTaImNY1HFTRCJknIyKSm86SzoevGxUGS4aJRaOujWMaDX5Q2YxOjOXzvC+MjPxWzPNyXStnL/Jic3PavOhE84jqm52t8m039YUcrnATkcsu26RiysKgw3krGyU9LkiXFiIqCg3E9VdcpmJOHTvC2kdPaMOVqSmeU52b1rnZVotfh2ZLm+fUa0YBEl/kPbvazOSBQ3zM3XbXl1VMKce3ff1V16iYN73xzaqvK4rCfO6fvqRiMuN8XrjpKU9RMWenZ1j7zJnTKiZb5rlZT5iVERF5/fr8nbhGrpc/b2IjSOoIvLXxd9JYqaL65jx+PXPG+QwPchOpsqEVmp/nOqygT8+784tV3p48rmJyXT0XVYjPF1srWu/x/YUp1j4Ta02O/ooyhAW93CpLLObLDxpaHqVRMGLkWDFMzkZiPac/Kc+fnYFyRcV8qnaMtRcNY79pUZRpyzWXqpheWBsjHgAAAACrBhYDAAAAQMrBYgAAAABIOVgMAAAAACmnZwFhxxCJ+AEXLvhKkEEUC8Fg1tfCu4wQDLpAi12mq1yEVW9pcVpxUIvaZmpcYOXq+jwKQ7zKU7Goqz71iUp+GUNgFBtCtTDi1ap843PVOS4Iqi1UVcyiMHeRwkQiomkh1DpsVGicb8yovnyGi32KhlmRH/PrWBl8loqpjPOKjI7WStVCLR6S9+rz//YVFVMM+Tk3DWFlXVTE67S1OLArq2lm9GNXMAReHSFeskyPmhE3iunOaqHSjz6LGxEFmaKKuX3v91XfyWku8Mqu0yKwSDzOG3ZeomI2buMmR7c/8ICK2X/8CD/Gop4nQt8SgfE+SyfmxP13VvlHcYus53Q1uHybFoNJEfbmMV0JdXx8I2uPjqxXMXPCbKwyqEXZM0IonS/qsVMa0mP3qJjTmxk97+ZyvGrieKgFoqEnvhusv18NwZ66oUZMLJ5La75yxOfv2DA9knNJZIzBltPCx2PiVIqBFqB3ymJjdV39sFCpsLYy0OqRtTHiAQAAALBqYDEAAAAApBwsBgAAAICU07NmIJAFQYjIE3k1KxfX6fI8jJWuk3mYmHReZHGhxtoHDh5TMd3iGdU3IPJpUUbnfA7OchOU9SM6d7ZxfJi1M57OQc0uaJOfmWle2OPk5KSKOXSAF4Bp13XRmEaT55OsQkWyYEatoXPMQ2PDqm/7ll18O/ry06nJo6x99KQuWFIa5eNhbJ0u+LQqGDm8SOhb9p+pqpiRIh+spbzOjWaEUYgf63HhiUIu9baOWYh0X0uYekVlrWXxxXo+FMWiiIjaWZ6L7R/foGK+efuduu/Ou1jb9emcbuzza/Qv3/imipme50WgDh8/qmKOzPAxHxumXpYgQBYdsjQDegCskSpEPZAxJszxIV6I5slXPknFdJ0Yu6UBFVNtcn2L1CUREWV8/hWR9/VXRhzosXsq5pqus22t8coFfFtWETtPnL+lGwmMPL4vpkcv0MctC7I5z9IM8P07Qxcm+2LD+art6f3fI65RLtT7z0j9XNbQDPTzecFZ2poewJsBAAAAIOVgMQAAAACkHCwGAAAAgJSDxQAAAACQcnoWEHqBFvR02lzM4DpaSCL9VlzGWH/E/DCmzmhjnBPHuWBtanJKxTR9LbzrF0YaxaIWgTWEEdHUqVMqZvIoF/nFkRbE1Gs11Te/wCuDTZ3WFduOHxOCqq42rtm+fTtrVypanOeEsUajpU1yRteNqb4r9lwttqPv0ZET3MDozvvuVTH5IV75rzxkVLpcDQw9TZgVlSI9LRo9HXIDHz80xIEeHzuxISCMhAFKbFZQM6qxSdGTISZTezMMjb513z7WPnJCj+/FRT1W5tr8uMO8FhCSEEbNGGZgX/jO93iHIUIjKRj0DaWxrQ6UQcbHLl4BYWSI4+Q4CIxKqFHIr7Hv6fm71eLjO8jq514aZrW6hulOfUH19Re4kVnY0eK4apfP8yWjIqF85NqWn46leBbPYSYwPqhM8qxr3cNYEeZ7xcg4D8N0SBYhNTThFIsKp9kBLQTNCQFhva5FxL2ANwMAAABAysFiAAAAAEg5WAwAAAAAKadnzUC7q3Mn3S7/+PR0VcVMn5ll7Ut3XaZiNk7wohrZ7DoVMzTIc+ZX79EJljir9QDlwRHWzhuahU6T54vnprV50R0/2M/aZ8+c1Nvp6CIxC4vcyKNe17qCbpvnayfW6cIj27btYO2tW7eqmIzIFz904EEVE+ksM42OjbJ2oaSLkfQN8ZzjyDq9//GNvFDUQkNfj9XBWPPK4WzkXUOZf3dGUk+mGc0cowgy05DWMfI+z4iRmhxrO21hQHNoTmtrPDL0ADmh+fCtgjDiZCzDE2F6JM8r6Vs5N2tFSOMYM8pIBV8sxMb5+MKcZ2ZOm50tLPI8ujTvISJqNbm+o+DrMSAlAq5YUjET23URpGuueTJr1xtaS/LQN7/G2s/cukfFHJviJm13ndKGVW1j7DiRx7fmPU/0WUWQnKo6pAfTjp07WXtUfOcQET1w4IDq27prG2t35qsq5tjJI7zDMLtri+Jo9UX9HdMLeDMAAAAApBwsBgAAAICUg8UAAAAAkHKwGAAAAABSTs8CwmJBiyLGRngFvOrcQRXzg9u/z7eT19uZWHcJaw8O6Mp646NcuBLHWpw2v6CFE6eneHXDU1UttqkMcOHh0Yf2q5h79vLzqC1UVUynrY+p1eLVBsNIG2T0lbmAccum7SomCETluT5tOrR+PRfynDp1VsWcmDyu+qQopt3V1ct+5MZrWXtg2Koqx4dTJzTMQFYF06mEN011muw837Wz2L9h6tQLpg5OHbdl1sP7PMs8yNqfUida11FyntdI3o4eKhT2sp2Lnti45pGoVEla2NoIuRGQ5+u5qSGEZv2GIZsT4k+X0/cgNm75voe5YK6ybqOKufLq61j75Zc8TcX8+523sfYdJ47oYzTEgdKOyxw5UhxpRokgw1TsJ/7LT7D2U571bBXzwQ9/RB9hyIV/Rxe02d7EFn7dpierKqY2y+91d7SpYnoBbwYAAACAlIPFAAAAAJBysBgAAAAAUg4WAwAAAEDK6VlAGMc6NBJClkpFV8TbuIE71XVCrfA5NcWFbtXpYyqmIypsZbJayHHyhP7c/ffyim2WQdrGDRtY+4EH7lMxJw4f4fsPDLeqWJ+bL3aY0ZZx5AthVFY6thFRp8VFQvlcWcUM9FdYe2Z2VsXMzE6rvjvuvp21i4NatDS6kR9Tl3SVu26bO6NljEqXq4GtO+tBjHbBqt1dnFXzehLsXTCeaMq/C0NkVMqUl2pmWguFv387f6bzee0q2m7y6naWw+XYCBd8l4uGw+WiFr6dOcqFyvVmV8WMbuTz7g+OH1IxxyN+jP0T4yrGquwYixKAsbMcCPn4llVfk04ugg6N+3HkMK/oWqhoAXy5qCu47rubC9VnjWq9IxX+uWJZO0BKp9duW1/rXsCbAQAAACDlYDEAAAAApBwsBgAAAICU07NmoFbTlfwaDZ6TtoqRPevZl/MY0tXhanWex56va2OgltAMxIZ5z3xd587ajhsytJotFTN1P89vLRpVnwaHee7G6+h8qlW1UJoM+YbWIBCVqBZrOq9fJ24IMjenjYE63ft5R2ZBxazfpnNOrsDPd2BMV40MhfbBGfexJKodZnwdsxp4vjEwDe2G8UnRTJdm4PEF18TEGHOBmENm57Q26JDIY2/ZtEXFhGIu7DaNanfiOalX9dzUWtBVMOMun/eqR7XZ2Z1z/DvlWKC1Uu0M33+mqLUPgeFtpoyIjKqNquBmrHPtLlo5/773jr2sfff92rSu1dVag5lJrnEL21qHNS++P8qjWjNBQjNg6eJ6AW8GAAAAgJSDxQAAAACQcrAYAAAAAFIOFgMAAABAyulZQOj5ujJWHIeirUUSzuOfCw0hRafLBRDVRS0EPD11irWzGX3oG9ZPqD4v4MKZo8cMQ6MuXxONT+iKgKPCUCkItUrj7FktsqzOcxFff5+uDDa2nm87Ji1ErNe4qPLBA3epmHUTXBz45KdcqmLKFS3AkVXHQsMApiOELF1DtOMJ0w7Ps6qJXcycpzIHfjrgPJGGZEkff2C7xsPY7rRZe8EQRYddLiCcPHpYxTRFddasIYAu9w2oPilGDNt1FTM7z+fwqvGghAGfQzJG5cys8blIzD1hqL+/fPE8+1nj69Dn+7Me5eocn5stbbJlBBTIW2uYHtXaXCjesapYCoF0Pjg/4TbeDAAAAAApB4sBAAAAIOVgMQAAAACknJ41A/V6U/X5Ip9SKBoFdpo8/z19VhdjCEWKfLaqTTS6Ec9v9Q/qwg+5kk7WrNvA8/8btozqz+V4QZ1sVhfYGejj+8sYRjaLi9oIaL7KDTn6+/VxDw1XxGe0WdB8lecAiwVtHjS2jvcNDudVTNbIi8Uid9U1DJ1kyq0b6Vxmsy10Be2LXTMg7jFy/+BxJmukf9vC8GxxXs8XniiaFhtF1LpCV9Ct6/mLhK7gBS9+iQr5yf/6OtX371//Gmsf2L9Pxdz+3dtYW+bwiYj6B3jRn6ihv4cazarqkwz26fkyEHN4taa3HSodnPH3s/ouWLkYHRFRLMQFLta6BieuSbumjYnkMWWMe90LeDMAAAAApBwsBgAAAICUg8UAAAAAkHKwGAAAAABSTs8CwnbXMG0IuFDBM8wvGm0uUsnktDhvbHyEtcuDOsbPcJVhoajNFwrGtgOfn2KhoEWO0sRDVhokIuoIsU1kVLjqL2hDn6EJUe3QqnwnzCbGS1pkuH4TFz6a9jc+F/t4GW1eZIlbMkIImg30tXWOX6NGU48HWdmQjO0AAHqn1dbPmayOGoZ6vpL+Nc2mITwL+RzmGRX6HPH9D48Nq5itO7ervleMvpK1jz58lYqp1/kxDefKKuaKp17H2pOnJlXMXXfvVX3DI/w75abnPlfFDAwOsvYde+9QMfse4JVgazVt3nR6khviRcb9IGd9f/L5MbRmdXEfs4Ymuyvu0YYRXXW2F/BmAAAAAEg5WAwAAAAAKQeLAQAAACDl9KwZ6BpGBhmR/253dK7EF0UTBod0oZ6+AZ7HzxQHVUwY8vySVTjJWQUrRG6/07Wy7fxzrVZbRWSE+4eX0fnwKDKOSRhJWJqBWOTuukbBikyGx8ROX2tVuynSjiWhUUXDE9ICyyAjn+Hbynp6HZkVGhJ49ADwn+PUKV20rdHg2qCn3/AsFZPJ8uJB3/7uN/TGhUbAmj89oSf6/t7bVczR/+fdqq/T4PN11NaGPvNN3he2jIJLd/E8fqur52bn63mu1eFz6L37HlQxpRI3Imq29bZHhrhpXWD8/XzaO83aXl6bvRVL2vRofGyctU8cPaJiuk1R4Mk3ZlVhjLTnsj06pgfwZgAAAABIOVgMAAAAACkHiwEAAAAg5WAxAAAAAKQczzlDUQYAAACA1IA3AwAAAEDKwWIAAAAASDlYDAAAAAApB4sBAAAAIOVgMQAAAACkHCwGAAAAgJSDxQAAAACQcrAYAAAAAFIOFgMAAABAyvn/AFUjmQ+xYC6mAAAAAElFTkSuQmCC",
      "text/plain": [
       "<Figure size 640x480 with 6 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "\n",
    "\n",
    "def visualize_model(best_ckpt_path, dataset_val):\n",
    "    num_class = 10\n",
    "    net = resnet50(num_class)\n",
    "    # 加载模型参数\n",
    "    param_dict = ms.load_checkpoint(best_ckpt_path)\n",
    "    ms.load_param_into_net(net, param_dict)\n",
    "    # 加载验证集的数据进行验证\n",
    "    data = next(dataset_val.create_dict_iterator())\n",
    "    images = data[\"image\"]\n",
    "    labels = data[\"label\"]\n",
    "    # 预测图像类别\n",
    "    output = net(data['image'])\n",
    "    pred = np.argmax(output.asnumpy(), axis=1)\n",
    "\n",
    "    # 图像分类\n",
    "    classes = []\n",
    "\n",
    "    with open(data_dir + \"/batches.meta.txt\", \"r\") as f:\n",
    "        for line in f:\n",
    "            line = line.rstrip()\n",
    "            if line:\n",
    "                classes.append(line)\n",
    "\n",
    "    # 显示图像及图像的预测值\n",
    "    plt.figure()\n",
    "    for i in range(6):\n",
    "        plt.subplot(2, 3, i + 1)\n",
    "        # 若预测正确，显示为蓝色；若预测错误，显示为红色\n",
    "        color = 'blue' if pred[i] == labels.asnumpy()[i] else 'red'\n",
    "        plt.title('predict:{}'.format(classes[pred[i]]), color=color)\n",
    "        picture_show = np.transpose(images.asnumpy()[i], (1, 2, 0))\n",
    "        mean = np.array([0.4914, 0.4822, 0.4465])\n",
    "        std = np.array([0.2023, 0.1994, 0.2010])\n",
    "        picture_show = std * picture_show + mean\n",
    "        picture_show = np.clip(picture_show, 0, 1)\n",
    "        plt.imshow(picture_show)\n",
    "        plt.axis('off')\n",
    "\n",
    "    plt.show()\n",
    "\n",
    "\n",
    "# 使用测试数据集进行验证\n",
    "visualize_model(best_ckpt_path=best_ckpt_path, dataset_val=dataset_val)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "018bf361-1d87-45f8-9fe1-9f63e910ea36",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.21"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
